blob: 824b7069065aef2b54f83c8dadb144ebfa8d9d32 [file] [log] [blame]
<!--
/***************************************************************************************************************************
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
***************************************************************************************************************************/
-->
{8.1.0-updated, 8.1.2-updated}
@Beanp Annotation
<p>
The {@link oaj.annotation.Beanp @Beanp} annotation is used to tailor how
individual bean properties are interpreted by the framework.
</p>
<p>
The {@link oaj.annotation.Beanp#name() @Beanp(name)} annotation
is used to override the name of the bean property.
</p>
<p class='bpcode w800'>
<jk>public class</jk> MyBean {
<ja>@Beanp</ja>(name=<js>"Bar"</js>)
<jk>public</jk> String getFoo() {...}
}
</p>
<p>
The {@link oaj.annotation.Name @Name} annotation is a shortcut for specifying a bean property name:
</p>
<p class='bpcode w800'>
<jk>public class</jk> MyBean {
<ja>@Name</ja>(<js>"Bar"</js>)
<jk>public</jk> String getFoo() {...}
}
</p>
<p>
If the {@link oaj.BeanContext#BEAN_beanFieldVisibility} setting on the bean context excludes this field
(e.g. the visibility is set to the default of PUBLIC, but the field is PROTECTED), this annotation
can be used to force the field to be identified as a property.
</p>
<p class='bpcode w800'>
<jk>public class</jk> MyBean {
<ja>@Beanp</ja>
<jk>protected</jk> String getFoo() {...}
}
</p>
<p>
The bean property named <js>"*"</js> is the designated "dynamic property" which allows for "extra" bean
properties not otherwise defined.
This is similar in concept to the Jackson <ja>@JsonGetterAll</ja> and <ja>@JsonSetterAll</ja>
annotations, but generalized for all supported marshall languages.
The primary purpose is for backwards compatibility in parsing newer streams with addition
information into older beans.
</p>
<p>
The following shows various ways of using dynamic bean properties.
</p>
<p class='bpcode w800'>
<jc>// Option #1 - A simple public Map field.</jc>
<jc>// The field name can be anything.</jc>
<jk>public class</jk> BeanWithDynaField {
<ja>@Beanp</ja>(name=<js>"*"</js>)
<jk>public</jk> Map&lt;String,Object&gt; extraStuff = <jk>new</jk> LinkedHashMap&lt;String,Object&gt;();
}
<jc>// Option #2 - Getters and setters.</jc>
<jc>// Method names can be anything.</jc>
<jc>// Getter must return a Map with String keys.</jc>
<jc>// Setter must take in two arguments, a String and Object.</jc>
<jk>public class</jk> BeanWithDynaMethods {
<ja>@Beanp</ja>(name=<js>"*"</js>)
<jk>public</jk> Map&lt;String,Object&gt; getMyExtraStuff() {
...
}
<ja>@Beanp</ja>(name=<js>"*"</js>)
<jk>public void</jk> setAnExtraField(String name, Object value) {
...
}
}
<jc>// Option #3 - Getter only.</jc>
<jc>// Properties will be added through the getter.</jc>
<jk>public class</jk> BeanWithDynaGetterOnly {
<ja>@Beanp</ja>(name=<js>"*"</js>)
<jk>public</jk> Map&lt;String,Object&gt; getMyExtraStuff() {
...
}
}
</p>
<p>
Similar rules apply for value types and swaps.
The property values optionally can be any serializable type or use swaps.
</p>
<p class='bpcode w800'>
<jc>// A serializable type other than Object.</jc>
<jk>public class</jk> BeanWithDynaFieldWithListValues {
<ja>@Beanp</ja>(name=<js>"*"</js>)
<jk>public</jk> Map&lt;String,List&lt;String&gt;&gt; getMyExtraStuff() {
...
}
}
<jc>// A swapped value.</jc>
<jk>public class</jk> BeanWithDynaFieldWithSwappedValues {
<ja>@Beanp</ja>(name=<js>"*"</js>, swap=TemporalCalendarSwap.IsoOffsetDateTime.<jk>class</jk>)
<jk>public</jk> Map&lt;String,Calendar&gt; getMyExtraStuff() {
...
}
}
</p>
<div class='info'>
Note that if you're not interested in these additional properties, you can also use the
{@link oaj.BeanContext#BEAN_ignoreUnknownBeanProperties} setting to ignore values
that don't fit into existing properties.
</div>
<p>
The {@link oaj.annotation.Beanp#value() @Beanp(value)} annotation
is a synonym for {@link oaj.annotation.Beanp#name() @Beanp(name)}.
Use it in cases where you're only specifying a name so that you can shorten your annotation.
</p>
<p>
The following annotations are equivalent:
</p>
<p class='bpcode w800'>
<ja>@Beanp</ja>(name=<js>"foo"</js>)
<ja>@Beanp</ja>(<js>"foo"</js>)
</p>
<p>
The {@link oaj.annotation.Beanp#type() @Beanp(type)} annotation
is used to identify a specialized class type for a generalized property.
Normally the type is inferred through reflection of the field type or getter return type.
However, you'll want to specify this value if you're parsing beans where the bean property class
is an interface or abstract class to identify the bean type to instantiate.
Otherwise, you may cause an {@link java.lang.InstantiationException} when trying to set these fields.
</p>
<p>
This property must denote a concrete class with a no-arg constructor.
</p>
<p class='bpcode w800'>
<jk>public class</jk> MyBean {
<jc>// Identify concrete type as a HashMap.</jc>
<ja>@Beanp</ja>(type=HashMap.<jk>class</jk>)
<jk>public</jk> Map <jf>p1</jf>;
}
</p>
<p>
The {@link oaj.annotation.BeanProperty#params() @Beanp(params)} annotation
is for bean properties of type map or collection.
It's used to identify the class types of the contents of the bean property object when
the general parameter types are interfaces or abstract classes.
</p>
<p class='bpcode w800'>
<jk>public class</jk> MyBean {
<jc>// This is a HashMap&lt;String,Integer&gt;.</jc>
<ja>@Beanp</ja>(type=HashMap.<jk>class</jk>, params={String.<jk>class</jk>,Integer.<jk>class</jk>})
<jk>public</jk> Map <jf>p1</jf>;
}
</p>
<p>
The {@link oaj.annotation.Beanp#properties() @Beanp(properties)}
annotation is used to limit which child properties are rendered by the serializers.
It can be used on any of the following bean property types:
</p>
<ul class='spaced-list'>
<li>Beans - Only render the specified properties of the bean.
<li>Maps - Only render the specified entries in the map.
<li>Bean/Map arrays - Same, but applied to each element in the array.
<li>Bean/Map collections - Same, but applied to each element in the collection.
</ul>
<p class='bpcode w800'>
<jk>public class</jk> MyClass {
<jc>// Only render 'f1' when serializing this bean property.</jc>
<ja>@Beanp</ja>(bpi={<js>"f1"</js>})
<jk>public</jk> MyChildClass x1 = <jk>new</jk> MyChildClass();
}
<jk>public class</jk> MyChildClass {
<jk>public int</jk> f1 = 1;
<jk>public int</jk> f2 = 2;
}
<jc>// Renders "{x1:{f1:1}}"</jc>
String json = JsonSerializer.<jsf>DEFAULT</jsf>.serialize(<jk>new</jk> MyClass());
</p>
<p>
The {@link oaj.annotation.Beanp#format() @Beanp(format)}
annotation specifies a String format for converting a bean property value to a formatted string.
</p>
<p class='bpcode w800'>
<jc>// Serialize a float as a string with 2 decimal places.</jc>
<ja>@Beanp</ja>(format=<js>"$%.2f"</js>)
<jk>public float</jk> <jf>price</jf>;
</p>