blob: 3b7d69931ebc8edcdd2e539d8b8d84dfe5120acb [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. *
// ***************************************************************************************************************************
package org.apache.juneau;
import static org.apache.juneau.collections.JsonMap.*;
import java.beans.*;
import java.io.*;
import java.lang.annotation.*;
import java.lang.reflect.*;
import java.util.*;
import java.util.function.*;
import org.apache.juneau.annotation.*;
import org.apache.juneau.collections.*;
import org.apache.juneau.internal.*;
import org.apache.juneau.swap.*;
import org.apache.juneau.utils.*;
/**
* Context class for classes that use {@link BeanContext} objects.
*
* <p>
* This abstraction exists to allow different kinds of subclasses (e.g. JsonSerilalizer, XmlParser...) to share bean context objects since
* bean context objects are heavyweight objects that cache metadata about encountered beans.
*
* <h5 class='section'>Notes:</h5><ul>
* <li class='note'>This class is thread safe and reusable.
* </ul>
*/
public abstract class BeanContextable extends Context {
//-----------------------------------------------------------------------------------------------------------------
// Builder
//-----------------------------------------------------------------------------------------------------------------
/**
* Builder class.
*/
@FluentSetters(ignore={"annotations","debug"})
public abstract static class Builder extends Context.Builder {
BeanContext.Builder bcBuilder;
BeanContext bc;
/**
* Constructor.
*
* All default settings.
*/
protected Builder() {
this.bcBuilder = BeanContext.create();
registerBuilders(bcBuilder);
}
/**
* Copy constructor.
*
* @param copyFrom The bean to copy from.
*/
protected Builder(BeanContextable copyFrom) {
super(copyFrom);
this.bcBuilder = copyFrom.getBeanContext().copy();
registerBuilders(bcBuilder);
}
/**
* Copy constructor.
*
* @param copyFrom The builder to copy from.
*/
protected Builder(Builder copyFrom) {
super(copyFrom);
this.bcBuilder = copyFrom.bcBuilder.copy();
this.bc = copyFrom.bc;
registerBuilders(bcBuilder);
}
@Override /* Context.Builder */
public abstract Builder copy();
@Override /* Context.Builder */
public HashKey hashKey() {
return HashKey.of(
super.hashKey(),
bcBuilder.hashKey(),
bc == null ? 0 : bc.hashKey
);
}
/**
* Returns the inner bean context builder.
*
* @return The inner bean context builder.
*/
public BeanContext.Builder beanContext() {
return bcBuilder;
}
/**
* Applies an operation to the inner bean context builder.
*
* @param operation The operation to apply.
* @return This object.
*/
public final Builder beanContext(Consumer<BeanContext.Builder> operation) {
operation.accept(beanContext());
return this;
}
//-----------------------------------------------------------------------------------------------------------------
// Properties
//-----------------------------------------------------------------------------------------------------------------
/**
* Overrides the bean context builder.
*
* <p>
* Used when sharing bean context builders across multiple context objects.
* For example, {@link org.apache.juneau.jsonschema.JsonSchemaGenerator.Builder} uses this to apply common bean settings with the JSON
* serializer and parser.
*
* @param value The new value for this setting.
* @return This object.
*/
@FluentSetter
public Builder beanContext(BeanContext.Builder value) {
this.bcBuilder = value;
return this;
}
/**
* Specifies an already-instantiated bean context to use.
*
* <p>
* Provides an optimization for cases where serializers and parsers can use an existing
* bean context without having to go through <c><jv>beanContext</jv>.copy().build()</c>.
* An example is {@link BeanContext#getBeanToStringSerializer()}.
*
* @param value The bean context to use.
* @return This object.
*/
@FluentSetter
public Builder beanContext(BeanContext value) {
this.bc = value;
return this;
}
/**
* Minimum bean class visibility.
*
* <p>
* Classes are not considered beans unless they meet the minimum visibility requirements.
* For example, if the visibility is <jsf>PUBLIC</jsf> and the bean class is <jk>protected</jk>, then the class
* will not be interpreted as a bean class and be serialized as a string.
* Use this setting to reduce the visibility requirement.
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// A bean with a protected class and one field.</jc>
* <jk>protected class</jk> MyBean {
* <jk>public</jk> String <jf>foo</jf> = <js>"bar"</js>;
* }
*
* <jc>// Create a serializer that's capable of serializing the class.</jc>
* WriterSerializer <jv>serializer</jv> = JsonSerializer
* .<jsm>create</jsm>()
* .beanClassVisibility(<jsf>PROTECTED</jsf>)
* .build();
*
* <jc>// Produces: {"foo","bar"}</jc>
* String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
* </p>
*
* <h5 class='section'>Notes:</h5>
* <ul>
* <li class='note'>The {@link Bean @Bean} annotation can be used on a non-public bean class to override this setting.
* <li class='note'>The {@link BeanIgnore @BeanIgnore} annotation can also be used on a public bean class to ignore it as a bean.
* </ul>
*
* <h5 class='section'>See Also:</h5>
* <ul>
* <li class='ja'>{@link BeanConfig#beanClassVisibility()}
* </ul>
*
* @param value
* The new value for this setting.
* <br>The default is {@link Visibility#PUBLIC}.
* @return This object.
*/
@FluentSetter
public Builder beanClassVisibility(Visibility value) {
bcBuilder.beanClassVisibility(value);
return this;
}
/**
* Minimum bean constructor visibility.
*
* <p>
* Only look for constructors with the specified minimum visibility.
*
* <p>
* This setting affects the logic for finding no-arg constructors for bean. Normally, only <jk>public</jk> no-arg
* constructors are used. Use this setting if you want to reduce the visibility requirement.
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// A bean with a protected constructor and one field.</jc>
* <jk>public class</jk> MyBean {
* <jk>public</jk> String <jf>foo</jf>;
*
* <jk>protected</jk> MyBean() {}
* }
*
* <jc>// Create a parser capable of calling the protected constructor.</jc>
* ReaderParser <jv>parser</jv> = ReaderParser
* .<jsm>create</jsm>()
* .beanConstructorVisibility(<jsf>PROTECTED</jsf>)
* .build();
*
* <jc>// Use it.</jc>
* MyBean <jv>bean</jv> = <jv>parser</jv>.parse(<js>"{foo:'bar'}"</js>, MyBean.<jk>class</jk>);
* </p>
*
* <h5 class='section'>Notes:</h5><ul>
* <li class='note'>The {@link Beanc @Beanc} annotation can also be used to expose a non-public constructor.
* <li class='note'>The {@link BeanIgnore @BeanIgnore} annotation can also be used on a public bean constructor to ignore it.
* </ul>
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='ja'>{@link BeanConfig#beanConstructorVisibility()}
* </ul>
*
* @param value
* The new value for this setting.
* <br>The default is {@link Visibility#PUBLIC}.
* @return This object.
*/
@FluentSetter
public Builder beanConstructorVisibility(Visibility value) {
bcBuilder.beanConstructorVisibility(value);
return this;
}
/**
* Minimum bean field visibility.
*
* <p>
* Only look for bean fields with the specified minimum visibility.
*
* <p>
* This affects which fields on a bean class are considered bean properties. Normally only <jk>public</jk> fields are considered.
* Use this setting if you want to reduce the visibility requirement.
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// A bean with a protected field.</jc>
* <jk>public class</jk> MyBean {
* <jk>protected</jk> String <jf>foo</jf> = <js>"bar"</js>;
* }
*
* <jc>// Create a serializer that recognizes the protected field.</jc>
* WriterSerializer <jv>serializer</jv> = JsonSerializer
* .<jsm>create</jsm>()
* .beanFieldVisibility(<jsf>PROTECTED</jsf>)
* .build();
*
* <jc>// Produces: {"foo":"bar"}</jc>
* String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
* </p>
*
* <p>
* Bean fields can be ignored as properties entirely by setting the value to {@link Visibility#NONE}
*
* <p class='bjava'>
* <jc>// Disable using fields as properties entirely.</jc>
* WriterSerializer <jv>serializer</jv> = JsonSerializer
* .<jsm>create</jsm>()
* .beanFieldVisibility(<jsf>NONE</jsf>)
* .build();
* </p>
*
* <h5 class='section'>Notes:</h5><ul>
* <li class='note'>The {@link Beanp @Beanp} annotation can also be used to expose a non-public field.
* <li class='note'>The {@link BeanIgnore @BeanIgnore} annotation can also be used on a public bean field to ignore it as a bean property.
* </ul>
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='ja'>{@link BeanConfig#beanFieldVisibility()}
* </ul>
*
* @param value
* The new value for this setting.
* <br>The default is {@link Visibility#PUBLIC}.
* @return This object.
*/
@FluentSetter
public Builder beanFieldVisibility(Visibility value) {
bcBuilder.beanFieldVisibility(value);
return this;
}
/**
* Bean interceptor.
*
* <p>
* Bean interceptors can be used to intercept calls to getters and setters and alter their values in transit.
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// Interceptor that strips out sensitive information.</jc>
* <jk>public class</jk> AddressInterceptor <jk>extends</jk> BeanInterceptor&lt;Address&gt; {
*
* <jk>public</jk> Object readProperty(Address <jv>bean</jv>, String <jv>name</jv>, Object <jv>value</jv>) {
* <jk>if</jk> (<js>"taxInfo"</js>.equals(<jv>name</jv>))
* <jk>return</jk> <js>"redacted"</js>;
* <jk>return</jk> <jv>value</jv>;
* }
*
* <jk>public</jk> Object writeProperty(Address <jv>bean</jv>, String <jv>name</jv>, Object <jv>value</jv>) {
* <jk>if</jk> (<js>"taxInfo"</js>.equals(<jv>name</jv>) &amp;&amp; <js>"redacted"</js>.equals(<jv>value</jv>))
* <jk>return</jk> TaxInfoUtils.<jsm>lookup</jsm>(<jv>bean</jv>.getStreet(), <jv>bean</jv>.getCity(), <jv>bean</jv>.getState());
* <jk>return</jk> <jv>value</jv>;
* }
* }
*
* <jc>// Our bean class.</jc>
* <jk>public class</jk> Address {
* <jk>public</jk> String getTaxInfo() {...}
* <jk>public void</jk> setTaxInfo(String <jv>value</jv>) {...}
* }
*
* <jc>// Register filter on serializer or parser.</jc>
* WriterSerializer <jv>serializer</jv> = JsonSerializer
* .<jsm>create</jsm>()
* .beanInterceptor(Address.<jk>class</jk>, AddressInterceptor.<jk>class</jk>)
* .build();
*
* <jc>// Produces: {"taxInfo":"redacted"}</jc>
* String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> Address());
* </p>
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='jc'>{@link BeanInterceptor}
* <li class='ja'>{@link Bean#interceptor() Bean(interceptor)}
* </ul>
*
* @param on The bean that the filter applies to.
* @param value
* The new value for this setting.
* @return This object.
*/
@FluentSetter
public Builder beanInterceptor(Class<?> on, Class<? extends BeanInterceptor<?>> value) {
bcBuilder.beanInterceptor(on, value);
return this;
}
/**
* BeanMap.put() returns old property value.
*
* <p>
* When enabled, then the {@link BeanMap#put(String,Object) BeanMap.put()} method will return old property
* values. Otherwise, it returns <jk>null</jk>.
*
* <p>
* Disabled by default because it introduces a slight performance penalty during serialization.
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// Create a context that creates BeanMaps with normal put() behavior.</jc>
* BeanContext <jv>context</jv> = BeanContext
* .<jsm>create</jsm>()
* .beanMapPutReturnsOldValue()
* .build();
*
* BeanMap&lt;MyBean&gt; <jv>beanMap</jv> = <jv>context</jv>.createSession().toBeanMap(<jk>new</jk> MyBean());
* <jv>beanMap</jv>.put(<js>"foo"</js>, <js>"bar"</js>);
* Object <jv>oldValue</jv> = <jv>beanMap</jv>.put(<js>"foo"</js>, <js>"baz"</js>); <jc>// oldValue == "bar"</jc>
* </p>
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='ja'>{@link BeanConfig#beanMapPutReturnsOldValue()}
* <li class='jm'>{@link BeanContext.Builder#beanMapPutReturnsOldValue()}
* </ul>
*
* @return This object.
*/
@FluentSetter
public Builder beanMapPutReturnsOldValue() {
bcBuilder.beanMapPutReturnsOldValue();
return this;
}
/**
* Minimum bean method visibility.
*
* <p>
* Only look for bean methods with the specified minimum visibility.
*
* <p>
* This affects which methods are detected as getters and setters on a bean class. Normally only <jk>public</jk> getters and setters are considered.
* Use this setting if you want to reduce the visibility requirement.
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// A bean with a protected getter.</jc>
* <jk>public class</jk> MyBean {
* <jk>public</jk> String getFoo() { <jk>return</jk> <js>"foo"</js>; }
* <jk>protected</jk> String getBar() { <jk>return</jk> <js>"bar"</js>; }
* }
*
* <jc>// Create a serializer that looks for protected getters and setters.</jc>
* WriterSerializer <jv>serializer</jv> = JsonSerializer
* .<jsm>create</jsm>()
* .beanMethodVisibility(<jsf>PROTECTED</jsf>)
* .build();
*
* <jc>// Produces: {"foo":"foo","bar":"bar"}</jc>
* String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
* </p>
*
* <h5 class='section'>Notes:</h5><ul>
* <li class='note'>The {@link Beanp @Beanp} annotation can also be used to expose a non-public method.
* <li class='note'>The {@link BeanIgnore @BeanIgnore} annotation can also be used on a public bean getter/setter to ignore it as a bean property.
* </ul>
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='ja'>{@link BeanConfig#beanMethodVisibility()}
* </ul>
*
* @param value
* The new value for this setting.
* <br>The default is {@link Visibility#PUBLIC}
* @return This object.
*/
@FluentSetter
public Builder beanMethodVisibility(Visibility value) {
bcBuilder.beanMethodVisibility(value);
return this;
}
/**
* Beans require no-arg constructors.
*
* <p>
* When enabled, a Java class must implement a default no-arg constructor to be considered a bean.
* Otherwise, the bean will be serialized as a string using the {@link Object#toString()} method.
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// A bean without a no-arg constructor.</jc>
* <jk>public class</jk> MyBean {
*
* <jc>// A property method.</jc>
* <jk>public</jk> String <jf>foo</jf> = <js>"bar"</js>;
*
* <jc>// A no-arg constructor</jc>
* <jk>public</jk> MyBean(String <jv>foo</jv>) {
* <jk>this</jk>.<jf>foo</jf> = <jv>foo</jv>;
* }
*
* <ja>@Override</ja>
* <jk>public</jk> String toString() {
* <jk>return</jk> <js>"bar"</js>;
* }
* }
*
* <jc>// Create a serializer that ignores beans without default constructors.</jc>
* WriterSerializer <jv>serializer</jv> = JsonSerializer
* .<jsm>create</jsm>()
* .beansRequireDefaultConstructor()
* .build();
*
* <jc>// Produces: "bar"</jc>
* String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
* </p>
*
* <h5 class='section'>Notes:</h5><ul>
* <li class='note'>The {@link Bean @Bean} annotation can be used on a bean class to override this setting.
* <li class='note'>The {@link BeanIgnore @BeanIgnore} annotation can also be used on a class to ignore it as a bean.
* </ul>
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='ja'>{@link BeanConfig#beansRequireDefaultConstructor()}
* <li class='jm'>{@link BeanContext.Builder#beansRequireDefaultConstructor()}
* </ul>
*
* @return This object.
*/
@FluentSetter
public Builder beansRequireDefaultConstructor() {
bcBuilder.beansRequireDefaultConstructor();
return this;
}
/**
* Beans require Serializable interface.
*
* <p>
* When enabled, a Java class must implement the {@link Serializable} interface to be considered a bean.
* Otherwise, the bean will be serialized as a string using the {@link Object#toString()} method.
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// A bean without a Serializable interface.</jc>
* <jk>public class</jk> MyBean {
*
* <jc>// A property method.</jc>
* <jk>public</jk> String <jf>foo</jf> = <js>"bar"</js>;
*
* <ja>@Override</ja>
* <jk>public</jk> String toString() {
* <jk>return</jk> <js>"bar"</js>;
* }
* }
*
* <jc>// Create a serializer that ignores beans not implementing Serializable.</jc>
* WriterSerializer <jv>serializer</jv> = JsonSerializer
* .<jsm>create</jsm>()
* .beansRequireSerializable()
* .build();
*
* <jc>// Produces: "bar"</jc>
* String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
* </p>
*
* <h5 class='section'>Notes:</h5><ul>
* <li class='note'>The {@link Bean @Bean} annotation can be used on a bean class to override this setting.
* <li class='note'>The {@link BeanIgnore @BeanIgnore} annotation can also be used on a class to ignore it as a bean.
* </ul>
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='ja'>{@link BeanConfig#beansRequireSerializable()}
* <li class='jm'>{@link BeanContext.Builder#beansRequireSerializable()}
* </ul>
*
* @return This object.
*/
@FluentSetter
public Builder beansRequireSerializable() {
bcBuilder.beansRequireSerializable();
return this;
}
/**
* Beans require setters for getters.
*
* <p>
* When enabled, ignore read-only properties (properties with getters but not setters).
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// A bean without a Serializable interface.</jc>
* <jk>public class</jk> MyBean {
*
* <jc>// A read/write property.</jc>
* <jk>public</jk> String getFoo() { <jk>return</jk> <js>"foo"</js>; }
* <jk>public void</jk> setFoo(String <jv>foo</jv>) { ... }
*
* <jc>// A read-only property.</jc>
* <jk>public</jk> String getBar() { <jk>return</jk> <js>"bar"</js>; }
* }
*
* <jc>// Create a serializer that ignores bean properties without setters.</jc>
* WriterSerializer <jv>serializer</jv> = JsonSerializer
* .<jsm>create</jsm>()
* .beansRequireSettersForGetters()
* .build();
*
* <jc>// Produces: {"foo":"foo"}</jc>
* String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
* </p>
*
* <h5 class='section'>Notes:</h5><ul>
* <li class='note'>The {@link Beanp @Beanp} annotation can be used on the getter to override this setting.
* <li class='note'>The {@link BeanIgnore @BeanIgnore} annotation can also be used on getters to ignore them as bean properties.
* </ul>
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='ja'>{@link BeanConfig#beansRequireSettersForGetters()}
* <li class='jm'>{@link BeanContext.Builder#beansRequireSettersForGetters()}
* </ul>
*
* @return This object.
*/
@FluentSetter
public Builder beansRequireSettersForGetters() {
bcBuilder.beansRequireSettersForGetters();
return this;
}
/**
* Beans don't require at least one property.
*
* <p>
* When enabled, then a Java class doesn't need to contain at least 1 property to be considered a bean.
* Otherwise, the bean will be serialized as a string using the {@link Object#toString()} method.
*
* <p>
* The {@link Bean @Bean} annotation can be used on a class to override this setting when <jk>true</jk>.
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// A bean with no properties.</jc>
* <jk>public class</jk> MyBean {
* }
*
* <jc>// Create a serializer that serializes beans even if they have zero properties.</jc>
* WriterSerializer <jv>serializer</jv> = JsonSerializer
* .<jsm>create</jsm>()
* .disableBeansRequireSomeProperties()
* .build();
*
* <jc>// Produces: {}</jc>
* String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
* </p>
*
* <h5 class='section'>Notes:</h5><ul>
* <li class='note'>The {@link Bean @Bean} annotation can be used on the class to force it to be recognized as a bean class
* even if it has no properties.
* </ul>
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='ja'>{@link BeanConfig#disableBeansRequireSomeProperties()}
* <li class='jm'>{@link BeanContext.Builder#disableBeansRequireSomeProperties()}
* </ul>
*
* @return This object.
*/
@FluentSetter
public Builder disableBeansRequireSomeProperties() {
bcBuilder.disableBeansRequireSomeProperties();
return this;
}
/**
* Bean property includes.
*
* <p>
* Specifies the set and order of names of properties associated with the bean class.
*
* <p>
* For example, <c>beanProperties(MyBean.<jk>class</jk>, <js>"foo,bar"</js>)</c> means only serialize the <c>foo</c> and
* <c>bar</c> properties on the specified bean. Likewise, parsing will ignore any bean properties not specified
* and either throw an exception or silently ignore them depending on whether {@link #ignoreUnknownBeanProperties()}
* has been called.
*
* <p>
* This value is entirely optional if you simply want to expose all the getters and public fields on
* a class as bean properties. However, it's useful if you want certain getters to be ignored or you want the properties to be
* serialized in a particular order. Note that on IBM JREs, the property order is the same as the order in the source code,
* whereas on Oracle JREs, the order is entirely random.
*
* <p>
* Setting applies to specified class and all subclasses.
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// A bean with 3 properties.</jc>
* <jk>public class</jk> MyBean {
* <jk>public</jk> String
* <jf>foo</jf> = <js>"foo"</js>,
* <jf>bar</jf> = <js>"bar"</js>,
* <jf>baz</jf> = <js>"baz"</js>;
* }
*
* <jc>// Create a serializer that includes only the 'foo' and 'bar' properties on the MyBean class.</jc>
* WriterSerializer <jv>serializer</jv> = JsonSerializer
* .<jsm>create</jsm>()
* .beanProperties(MyBean.<jk>class</jk>, <js>"foo,bar"</js>)
* .build();
*
* <jc>// Produces: {"foo":"foo","bar":"bar"}</jc>
* String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
* </p>
*
* <p>
* This method is functionally equivalent to the following code:
* <p class='bjava'>
* <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>beanClass</jv>).properties(<jv>properties</jv>).build());
* </p>
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='jm'>{@link Bean#properties()}/{@link Bean#p()} - On an annotation on the bean class itself.
* </ul>
*
* @param beanClass The bean class.
* @param properties Comma-delimited list of property names.
* @return This object.
*/
@FluentSetter
public Builder beanProperties(Class<?> beanClass, String properties) {
bcBuilder.beanProperties(beanClass, properties);
return this;
}
/**
* Bean property includes.
*
* <p>
* Specifies the set and order of names of properties associated with bean classes.
*
* <p>
* For example, <c>beanProperties(AMap.<jsm>of</jsm>(<js>"MyBean"</js>, <js>"foo,bar"</js>))</c> means only serialize the <c>foo</c> and
* <c>bar</c> properties on the specified bean. Likewise, parsing will ignore any bean properties not specified
* and either throw an exception or silently ignore them depending on whether {@link #ignoreUnknownBeanProperties()}
* has been called.
*
* <p>
* This value is entirely optional if you simply want to expose all the getters and public fields on
* a class as bean properties. However, it's useful if you want certain getters to be ignored or you want the properties to be
* serialized in a particular order. Note that on IBM JREs, the property order is the same as the order in the source code,
* whereas on Oracle JREs, the order is entirely random.
*
* <p>
* Setting applies to specified class and all subclasses.
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// A bean with 3 properties.</jc>
* <jk>public class</jk> MyBean {
* <jk>public</jk> String
* <jf>foo</jf> = <js>"foo"</js>,
* <jf>bar</jf> = <js>"bar"</js>,
* <jf>baz</jf> = <js>"baz"</js>;
* }
*
* <jc>// Create a serializer that includes only the 'foo' and 'bar' properties on the MyBean class.</jc>
* WriterSerializer <jv>serializer</jv> = JsonSerializer
* .<jsm>create</jsm>()
* .beanProperties(AMap.<jsm>of</jsm>(<js>"MyBean"</js>, <js>"foo,bar"</js>))
* .build();
*
* <jc>// Produces: {"foo":"foo","bar":"bar"}</jc>
* String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
* </p>
*
* <p>
* This method is functionally equivalent to the following code for each entry:
* <p class='bjava'>
* <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>key</jv>).properties(<jv>value</jv>.toString()).build());
* </p>
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='jma'>{@link Bean#properties()} / {@link Bean#p()}- On an annotation on the bean class itself.
* </ul>
*
* @param values
* The values to add to this builder.
* <br>Keys are bean class names which can be a simple name, fully-qualified name, or <js>"*"</js> for all beans.
* <br>Values are comma-delimited lists of property names. Non-String objects are first converted to Strings.
* @return This object.
*/
@FluentSetter
public Builder beanProperties(Map<String,Object> values) {
bcBuilder.beanProperties(values);
return this;
}
/**
* Bean property includes.
*
* <p>
* Specifies the set and order of names of properties associated with the bean class.
*
* <p>
* For example, <c>beanProperties(<js>"MyBean"</js>, <js>"foo,bar"</js>)</c> means only serialize the <c>foo</c> and
* <c>bar</c> properties on the specified bean. Likewise, parsing will ignore any bean properties not specified
* and either throw an exception or silently ignore them depending on whether {@link #ignoreUnknownBeanProperties()}
* has been called.
*
* <p>
* This value is entirely optional if you simply want to expose all the getters and public fields on
* a class as bean properties. However, it's useful if you want certain getters to be ignored or you want the properties to be
* serialized in a particular order. Note that on IBM JREs, the property order is the same as the order in the source code,
* whereas on Oracle JREs, the order is entirely random.
*
* <p>
* Setting applies to specified class and all subclasses.
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// A bean with 3 properties.</jc>
* <jk>public class</jk> MyBean {
* <jk>public</jk> String
* <jf>foo</jf> = <js>"foo"</js>,
* <jf>bar</jf> = <js>"bar"</js>,
* <jf>baz</jf> = <js>"baz"</js>;
* }
*
* <jc>// Create a serializer that includes only the 'foo' and 'bar' properties on the MyBean class.</jc>
* WriterSerializer <jv>serializer</jv> = JsonSerializer
* .<jsm>create</jsm>()
* .beanProperties(<js>"MyBean"</js>, <js>"foo,bar"</js>)
* .build();
*
* <jc>// Produces: {"foo":"foo","bar":"bar"}</jc>
* String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
* </p>
*
* <p>
* This method is functionally equivalent to the following code:
* <p class='bjava'>
* <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>beanClassName</jv>).properties(<jv>properties</jv>).build());
* </p>
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='jma'>{@link Bean#properties()} / {@link Bean#p()} - On an annotation on the bean class itself.
* </ul>
*
* @param beanClassName
* The bean class name.
* <br>Can be a simple name, fully-qualified name, or <js>"*"</js> for all beans.
* @param properties Comma-delimited list of property names.
* @return This object.
*/
@FluentSetter
public Builder beanProperties(String beanClassName, String properties) {
bcBuilder.beanProperties(beanClassName, properties);
return this;
}
/**
* Bean property excludes.
*
* <p>
* Specifies to exclude the specified list of properties for the specified bean class.
*
* <p>
* Same as {@link #beanProperties(Class, String)} except you specify a list of bean property names that you want to exclude from
* serialization.
*
* <p>
* Setting applies to specified class and all subclasses.
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// A bean with 3 properties.</jc>
* <jk>public class</jk> MyBean {
* <jk>public</jk> String
* <jf>foo</jf> = <js>"foo"</js>,
* <jf>bar</jf> = <js>"bar"</js>,
* <jf>baz</jf> = <js>"baz"</js>;
* }
*
* <jc>// Create a serializer that excludes the "bar" and "baz" properties on the MyBean class.</jc>
* WriterSerializer <jv>serializer</jv> = JsonSerializer
* .<jsm>create</jsm>()
* .beanPropertiesExcludes(MyBean.<jk>class</jk>, <js>"bar,baz"</js>)
* .build();
*
* <jc>// Produces: {"foo":"foo"}</jc>
* String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
* </p>
*
* <p>
* This method is functionally equivalent to the following code:
* <p class='bjava'>
* <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>beanClass</jv>).excludeProperties(<jv>properties</jv>).build());
* </p>
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='jma'>{@link Bean#excludeProperties()} / {@link Bean#xp()}
* </ul>
*
* @param beanClass The bean class.
* @param properties Comma-delimited list of property names.
* @return This object.
*/
@FluentSetter
public Builder beanPropertiesExcludes(Class<?> beanClass, String properties) {
bcBuilder.beanPropertiesExcludes(beanClass, properties);
return this;
}
/**
* Bean property excludes.
*
* <p>
* Specifies to exclude the specified list of properties for the specified bean classes.
*
* <p>
* Same as {@link #beanProperties(Map)} except you specify a list of bean property names that you want to exclude from
* serialization.
*
* <p>
* Setting applies to specified class and all subclasses.
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// A bean with 3 properties.</jc>
* <jk>public class</jk> MyBean {
* <jk>public</jk> String
* <jf>foo</jf> = <js>"foo"</js>,
* <jf>bar</jf> = <js>"bar"</js>,
* <jf>baz</jf> = <js>"baz"</js>;
* }
*
* <jc>// Create a serializer that excludes the "bar" and "baz" properties on the MyBean class.</jc>
* WriterSerializer <jv>serializer</jv> = JsonSerializer
* .<jsm>create</jsm>()
* .beanPropertiesExcludes(AMap.of(<js>"MyBean"</js>, <js>"bar,baz"</js>))
* .build();
*
* <jc>// Produces: {"foo":"foo"}</jc>
* String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
* </p>
*
* <p>
* This method is functionally equivalent to the following code for each entry:
* <p class='bjava'>
* <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>key</jv>).excludeProperties(<jv>value</jv>.toString()).build());
* </p>
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='jma'>{@link Bean#excludeProperties()} / {@link Bean#xp()}
* </ul>
*
* @param values
* The values to add to this builder.
* <br>Keys are bean class names which can be a simple name, fully-qualified name, or <js>"*"</js> for all beans.
* <br>Values are comma-delimited lists of property names. Non-String objects are first converted to Strings.
* @return This object.
*/
@FluentSetter
public Builder beanPropertiesExcludes(Map<String,Object> values) {
bcBuilder.beanPropertiesExcludes(values);
return this;
}
/**
* Bean property excludes.
*
* <p>
* Specifies to exclude the specified list of properties for the specified bean class.
*
* <p>
* Same as {@link #beanPropertiesExcludes(String, String)} except you specify a list of bean property names that you want to exclude from
* serialization.
*
* <p>
* Setting applies to specified class and all subclasses.
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// A bean with 3 properties.</jc>
* <jk>public class</jk> MyBean {
* <jk>public</jk> String
* <jf>foo</jf> = <js>"foo"</js>,
* <jf>bar</jf> = <js>"bar"</js>,
* <jf>baz</jf> = <js>"baz"</js>;
* }
*
* <jc>// Create a serializer that excludes the "bar" and "baz" properties on the MyBean class.</jc>
* WriterSerializer <jv>serializer</jv> = JsonSerializer
* .<jsm>create</jsm>()
* .beanPropertiesExcludes(<js>"MyBean"</js>, <js>"bar,baz"</js>)
* .build();
*
* <jc>// Produces: {"foo":"foo"}</jc>
* String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
* </p>
*
* <p>
* This method is functionally equivalent to the following code:
* <p class='bjava'>
* <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>beanClassName</jv>).excludeProperties(<jv>properties</jv>).build());
* </p>
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='jma'>{@link Bean#excludeProperties()} / {@link Bean#xp()}
* </ul>
*
* @param beanClassName
* The bean class name.
* <br>Can be a simple name, fully-qualified name, or <js>"*"</js> for all bean classes.
* @param properties Comma-delimited list of property names.
* @return This object.
*/
@FluentSetter
public Builder beanPropertiesExcludes(String beanClassName, String properties) {
bcBuilder.beanPropertiesExcludes(beanClassName, properties);
return this;
}
/**
* Read-only bean properties.
*
* <p>
* Specifies one or more properties on a bean that are read-only despite having valid getters.
* Serializers will serialize such properties as usual, but parsers will silently ignore them.
* Note that this is different from the {@link #beanProperties(Class,String) beanProperties}/{@link #beanPropertiesExcludes(Class,String) beanPropertiesExcludes} settings which include or exclude properties
* for both serializers and parsers.
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// A bean with 3 properties.</jc>
* <jk>public class</jk> MyBean {
* <jk>public</jk> String <jf>foo</jf>, <jf>bar</jf>, <jf>baz</jf>;
* }
*
* <jc>// Create a serializer with read-only property settings.</jc>
* WriterSerializer <jv>serializer</jv> = JsonSerializer
* .<jsm>create</jsm>()
* .beanPropertiesReadOnly(MyBean.<jk>class</jk>, <js>"bar,baz"</js>)
* .build();
*
* <jc>// All 3 properties will be serialized.</jc>
* String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
*
* <jc>// Create a parser with read-only property settings.</jc>
* ReaderParser <jv>parser</jv> = JsonParser
* .<jsm>create</jsm>()
* .beanPropertiesReadOnly(MyBean.<jk>class</jk>, <js>"bar,baz"</js>)
* .ignoreUnknownBeanProperties()
* .build();
*
* <jc>// Parser ignores bar and baz properties.</jc>
* MyBean <jv>bean</jv> = <jv>parser</jv>.parse(<js>"{foo:'foo',bar:'bar',baz:'baz'}"</js>, MyBean.<jk>class</jk>);
* </p>
*
* <p>
* This method is functionally equivalent to the following code:
* <p class='bjava'>
* <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>beanClass</jv>).readOnlyProperties(<jv>properties</jv>).build());
* </p>
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='jma'>{@link Bean#readOnlyProperties()} / {@link Bean#ro()}
* </ul>
*
* @param beanClass The bean class.
* @param properties Comma-delimited list of property names.
* @return This object.
*/
@FluentSetter
public Builder beanPropertiesReadOnly(Class<?> beanClass, String properties) {
bcBuilder.beanPropertiesReadOnly(beanClass, properties);
return this;
}
/**
* Read-only bean properties.
*
* <p>
* Specifies one or more properties on beans that are read-only despite having valid getters.
* Serializers will serialize such properties as usual, but parsers will silently ignore them.
* Note that this is different from the {@link #beanProperties(Class,String) beanProperties}/{@link #beanPropertiesExcludes(Class,String) beanPropertiesExcludes} settings which include or exclude properties
* for both serializers and parsers.
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// A bean with 3 properties.</jc>
* <jk>public class</jk> MyBean {
* <jk>public</jk> String <jf>foo</jf>, <jf>bar</jf>, <jf>baz</jf>;
* }
*
* <jc>// Create a serializer with read-only property settings.</jc>
* WriterSerializer <jv>serializer</jv> = JsonSerializer
* .<jsm>create</jsm>()
* .beanPropertiesReadOnly(AMap.<jsm>of</jsm>(<js>"MyBean"</js>, <js>"bar,baz"</js>))
* .build();
*
* <jc>// All 3 properties will be serialized.</jc>
* String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
*
* <jc>// Create a parser with read-only property settings.</jc>
* ReaderParser <jv>parser</jv> = JsonParser
* .<jsm>create</jsm>()
* .beanPropertiesReadOnly(AMap.<jsm>of</jsm>(<js>"MyBean"</js>, <js>"bar,baz"</js>))
* .ignoreUnknownBeanProperties()
* .build();
*
* <jc>// Parser ignores bar and baz properties.</jc>
* MyBean <jv>bean</jv> = <jv>parser</jv>.parse(<js>"{foo:'foo',bar:'bar',baz:'baz'}"</js>, MyBean.<jk>class</jk>);
* </p>
*
* <p>
* This method is functionally equivalent to the following code for each entry:
* <p class='bjava'>
* <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>key</jv>).readOnlyProperties(<jv>value</jv>.toString()).build());
* </p>
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='jma'>{@link Bean#readOnlyProperties()} / {@link Bean#ro()}
* </ul>
*
* @param values
* The values to add to this builder.
* <br>Keys are bean class names which can be a simple name, fully-qualified name, or <js>"*"</js> for all beans.
* <br>Values are comma-delimited lists of property names. Non-String objects are first converted to Strings.
* @return This object.
*/
@FluentSetter
public Builder beanPropertiesReadOnly(Map<String,Object> values) {
bcBuilder.beanPropertiesReadOnly(values);
return this;
}
/**
* Read-only bean properties.
*
* <p>
* Specifies one or more properties on a bean that are read-only despite having valid getters.
* Serializers will serialize such properties as usual, but parsers will silently ignore them.
* Note that this is different from the {@link #beanProperties(Class,String) beanProperties}/{@link #beanPropertiesExcludes(Class,String) beanPropertiesExcludes} settings which include or exclude properties
* for both serializers and parsers.
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// A bean with 3 properties.</jc>
* <jk>public class</jk> MyBean {
* <jk>public</jk> String <jf>foo</jf>, <jf>bar</jf>, <jf>baz</jf>;
* }
*
* <jc>// Create a serializer with read-only property settings.</jc>
* WriterSerializer <jv>serializer</jv> = JsonSerializer
* .<jsm>create</jsm>()
* .beanPropertiesReadOnly(<js>"MyBean"</js>, <js>"bar,baz"</js>)
* .build();
*
* <jc>// All 3 properties will be serialized.</jc>
* String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
*
* <jc>// Create a parser with read-only property settings.</jc>
* ReaderParser <jv>parser</jv> = JsonParser
* .<jsm>create</jsm>()
* .beanPropertiesReadOnly(<js>"MyBean"</js>, <js>"bar,baz"</js>)
* .ignoreUnknownBeanProperties()
* .build();
*
* <jc>// Parser ignores bar and baz properties.</jc>
* MyBean <jv>bean</jv> = <jv>parser</jv>.parse(<js>"{foo:'foo',bar:'bar',baz:'baz'}"</js>, MyBean.<jk>class</jk>);
* </p>
*
* <p>
* This method is functionally equivalent to the following code:
* <p class='bjava'>
* <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>beanClassName</jv>).readOnlyProperties(<jv>properties</jv>).build());
* </p>
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='jma'>{@link Bean#readOnlyProperties()} / {@link Bean#ro()}
* </ul>
*
* @param beanClassName
* The bean class name.
* <br>Can be a simple name, fully-qualified name, or <js>"*"</js> for all bean classes.
* @param properties Comma-delimited list of property names.
* @return This object.
*/
@FluentSetter
public Builder beanPropertiesReadOnly(String beanClassName, String properties) {
bcBuilder.beanPropertiesReadOnly(beanClassName, properties);
return this;
}
/**
* Write-only bean properties.
*
* <p>
* Specifies one or more properties on a bean that are write-only despite having valid setters.
* Parsers will parse such properties as usual, but serializers will silently ignore them.
* Note that this is different from the {@link #beanProperties(Class,String) beanProperties}/{@link #beanPropertiesExcludes(Class,String) beanPropertiesExcludes} settings which include or exclude properties
* for both serializers and parsers.
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// A bean with 3 properties.</jc>
* <jk>public class</jk> MyBean {
* <jk>public</jk> String <jf>foo</jf>, <jf>bar</jf>, <jf>baz</jf>;
* }
*
* <jc>// Create a serializer with write-only property settings.</jc>
* WriterSerializer <jv>serializer</jv> = JsonSerializer
* .<jsm>create</jsm>()
* .beanPropertiesWriteOnly(MyBean.<jk>class</jk>, <js>"bar,baz"</js>)
* .build();
*
* <jc>// Only foo will be serialized.</jc>
* String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
*
* <jc>// Create a parser with write-only property settings.</jc>
* ReaderParser <jv>parser</jv> = JsonParser
* .<jsm>create</jsm>()
* .beanPropertiesWriteOnly(MyBean.<jk>class</jk>, <js>"bar,baz"</js>)
* .build();
*
* <jc>// Parser parses all 3 properties.</jc>
* MyBean <jv>bean</jv> = <jv>parser</jv>.parse(<js>"{foo:'foo',bar:'bar',baz:'baz'}"</js>, MyBean.<jk>class</jk>);
* </p>
*
* <p>
* This method is functionally equivalent to the following code:
* <p class='bjava'>
* <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>beanClass</jv>).writeOnlyProperties(<jv>properties</jv>).build());
* </p>
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='jma'>{@link Bean#writeOnlyProperties()} / {@link Bean#wo()}
* </ul>
*
* @param beanClass The bean class.
* @param properties Comma-delimited list of property names.
* @return This object.
*/
@FluentSetter
public Builder beanPropertiesWriteOnly(Class<?> beanClass, String properties) {
bcBuilder.beanPropertiesWriteOnly(beanClass, properties);
return this;
}
/**
* Write-only bean properties.
*
* <p>
* Specifies one or more properties on a bean that are write-only despite having valid setters.
* Parsers will parse such properties as usual, but serializers will silently ignore them.
* Note that this is different from the {@link #beanProperties(Class,String) beanProperties}/{@link #beanPropertiesExcludes(Class,String) beanPropertiesExcludes} settings which include or exclude properties
* for both serializers and parsers.
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// A bean with 3 properties.</jc>
* <jk>public class</jk> MyBean {
* <jk>public</jk> String <jf>foo</jf>, <jf>bar</jf>, <jf>baz</jf>;
* }
*
* <jc>// Create a serializer with write-only property settings.</jc>
* WriterSerializer <jv>serializer</jv> = JsonSerializer
* .<jsm>create</jsm>()
* .beanPropertiesWriteOnly(AMap.<jsm>of</jsm>(<js>"MyBean"</js>, <js>"bar,baz"</js>))
* .build();
*
* <jc>// Only foo will be serialized.</jc>
* String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
*
* <jc>// Create a parser with write-only property settings.</jc>
* ReaderParser <jv>parser</jv> = JsonParser
* .<jsm>create</jsm>()
* .beanPropertiesWriteOnly(AMap.<jsm>of</jsm>(<js>"MyBean"</js>, <js>"bar,baz"</js>))
* .build();
*
* <jc>// Parser parses all 3 properties.</jc>
* MyBean <jv>bean</jv> = <jv>parser</jv>.parse(<js>"{foo:'foo',bar:'bar',baz:'baz'}"</js>, MyBean.<jk>class</jk>);
* </p>
*
* <p>
* This method is functionally equivalent to the following code for each entry:
* <p class='bjava'>
* <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>key</jv>).writeOnlyProperties(<jv>value</jv>.toString()).build());
* </p>
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='jma'>{@link Bean#writeOnlyProperties()} / {@link Bean#wo()}
* </ul>
*
* @param values
* The values to add to this builder.
* <br>Keys are bean class names which can be a simple name, fully-qualified name, or <js>"*"</js> for all beans.
* <br>Values are comma-delimited lists of property names. Non-String objects are first converted to Strings.
* @return This object.
*/
@FluentSetter
public Builder beanPropertiesWriteOnly(Map<String,Object> values) {
bcBuilder.beanPropertiesWriteOnly(values);
return this;
}
/**
* Write-only bean properties.
*
* <p>
* Specifies one or more properties on a bean that are write-only despite having valid setters.
* Parsers will parse such properties as usual, but serializers will silently ignore them.
* Note that this is different from the {@link #beanProperties(Class,String) beanProperties}/{@link #beanPropertiesExcludes(Class,String) beanPropertiesExcludes} settings which include or exclude properties
* for both serializers and parsers.
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// A bean with 3 properties.</jc>
* <jk>public class</jk> MyBean {
* <jk>public</jk> String <jf>foo</jf>, <jf>bar</jf>, <jf>baz</jf>;
* }
*
* <jc>// Create a serializer with write-only property settings.</jc>
* WriterSerializer <jv>serializer</jv> = JsonSerializer
* .<jsm>create</jsm>()
* .beanPropertiesWriteOnly(<js>"MyBean"</js>, <js>"bar,baz"</js>)
* .build();
*
* <jc>// Only foo will be serialized.</jc>
* String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
*
* <jc>// Create a parser with write-only property settings.</jc>
* ReaderParser <jv>parser</jv> = JsonParser
* .<jsm>create</jsm>()
* .beanPropertiesWriteOnly(<js>"MyBean"</js>, <js>"bar,baz"</js>)
* .build();
*
* <jc>// Parser parses all 3 properties.</jc>
* MyBean <jv>bean</jv> = <jv>parser</jv>.parse(<js>"{foo:'foo',bar:'bar',baz:'baz'}"</js>, MyBean.<jk>class</jk>);
* </p>
*
* <p>
* This method is functionally equivalent to the following code:
* <p class='bjava'>
* <jv>builder</jv>.annotations(BeanAnnotation.<jsm>create</jsm>(<jv>beanClassName</jv>).writeOnlyProperties(<jv>properties</jv>).build());
* </p>
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='jma'>{@link Bean#writeOnlyProperties()} / {@link Bean#wo()}
* </ul>
*
* @param beanClassName
* The bean class name.
* <br>Can be a simple name, fully-qualified name, or <js>"*"</js> for all bean classes.
* @param properties Comma-delimited list of property names.
* @return This object.
*/
@FluentSetter
public Builder beanPropertiesWriteOnly(String beanClassName, String properties) {
bcBuilder.beanPropertiesWriteOnly(beanClassName, properties);
return this;
}
/**
* Bean dictionary.
*
* <p>
* The list of classes that make up the bean dictionary in this bean context.
*
* <p>
* Values are prepended to the list so that later calls can override classes of earlier calls.
*
* <p>
* A dictionary is a name/class mapping used to find class types during parsing when they cannot be inferred
* through reflection. The names are defined through the {@link Bean#typeName() @Bean(typeName)} annotation defined
* on the bean class. For example, if a class <c>Foo</c> has a type-name of <js>"myfoo"</js>, then it would end up
* serialized as <js>"{_type:'myfoo',...}"</js> in JSON
* or <js>"&lt;myfoo&gt;...&lt;/myfoo&gt;"</js> in XML.
*
* <p>
* This setting tells the parsers which classes to look for when resolving <js>"_type"</js> attributes.
*
* <p>
* Values can consist of any of the following types:
* <ul>
* <li>Any bean class that specifies a value for {@link Bean#typeName() @Bean(typeName)}.
* <li>Any subclass of {@link BeanDictionaryList} containing a collection of bean classes with type name annotations.
* <li>Any subclass of {@link BeanDictionaryMap} containing a mapping of type names to classes without type name annotations.
* <li>Any array or collection of the objects above.
* </ul>
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// POJOs with @Bean(name) annotations.</jc>
* <ja>@Bean</ja>(typeName=<js>"foo"</js>)
* <jk>public class</jk> Foo {...}
* <ja>@Bean</ja>(typeName=<js>"bar"</js>)
* <jk>public class</jk> Bar {...}
*
* <jc>// Create a parser and tell it which classes to try to resolve.</jc>
* ReaderParser <jv>parser</jv> = JsonParser
* .<jsm>create</jsm>()
* .dictionary(Foo.<jk>class</jk>, Bar.<jk>class</jk>)
* .addBeanTypes()
* .build();
*
* <jc>// A bean with a field with an indeterminate type.</jc>
* <jk>public class</jk> MyBean {
* <jk>public</jk> Object <jf>mySimpleField</jf>;
* }
*
* <jc>// Parse bean.</jc>
* MyBean <jv>bean</jv> = <jv>parser</jv>.parse(<js>"{mySimpleField:{_type:'foo',...}}"</js>, MyBean.<jk>class</jk>);
* </p>
*
* <p>
* Another option is to use the {@link Bean#dictionary()} annotation on the POJO class itself:
*
* <p class='bjava'>
* <jc>// Instead of by parser, define a bean dictionary on a class through an annotation.</jc>
* <jc>// This applies to all properties on this class and all subclasses.</jc>
* <ja>@Bean</ja>(dictionary={Foo.<jk>class</jk>,Bar.<jk>class</jk>})
* <jk>public class</jk> MyBean {
* <jk>public</jk> Object <jf>mySimpleField</jf>; <jc>// May contain Foo or Bar object.</jc>
* <jk>public</jk> Map&lt;String,Object&gt; <jf>myMapField</jf>; <jc>// May contain Foo or Bar objects.</jc>
* }
* </p>
*
* <p>
* A typical usage is to allow for HTML documents to be parsed back into HTML beans:
* <p class='bjava'>
* <jc>// Use the predefined HTML5 bean dictionary which is a BeanDictionaryList.</jc>
* ReaderParser <jv>parser</jv> = HtmlParser
* .<jsm>create</jsm>()
* .dictionary(HtmlBeanDictionary.<jk>class</jk>)
* .build();
*
* <jc>// Parse an HTML body into HTML beans.</jc>
* Body <jv>body</jv> = <jv>parser</jv>.parse(<js>"&lt;body&gt;&lt;ul&gt;&lt;li&gt;foo&lt;/li&gt;&lt;li&gt;bar&lt;/li&gt;&lt;/ul&gt;"</js>, Body.<jk>class</jk>);
* </p>
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='ja'>{@link Bean#dictionary()}
* <li class='ja'>{@link Beanp#dictionary()}
* <li class='ja'>{@link BeanConfig#dictionary()}
* <li class='ja'>{@link BeanConfig#dictionary_replace()}
* </ul>
*
* @param values
* The values to add to this setting.
* @return This object.
*/
@FluentSetter
public Builder beanDictionary(Class<?>...values) {
bcBuilder.beanDictionary(values);
return this;
}
/**
* Bean dictionary.
*
* <p>
* This is identical to {@link #beanDictionary(Class...)}, but specifies a dictionary within the context of
* a single class as opposed to globally.
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// POJOs with @Bean(name) annotations.</jc>
* <ja>@Bean</ja>(typeName=<js>"foo"</js>)
* <jk>public class</jk> Foo {...}
* <ja>@Bean</ja>(typeName=<js>"bar"</js>)
* <jk>public class</jk> Bar {...}
*
* <jc>// A bean with a field with an indeterminate type.</jc>
* <jk>public class</jk> MyBean {
* <jk>public</jk> Object <jf>mySimpleField</jf>;
* }
*
* <jc>// Create a parser and tell it which classes to try to resolve.</jc>
* ReaderParser <jv>parser</jv> = JsonParser
* .<jsm>create</jsm>()
* .dictionaryOn(MyBean.<jk>class</jk>, Foo.<jk>class</jk>, Bar.<jk>class</jk>)
* .build();
*
* <jc>// Parse bean.</jc>
* MyBean <jv>bean</jv> = <jv>parser</jv>.parse(<js>"{mySimpleField:{_type:'foo',...}}"</js>, MyBean.<jk>class</jk>);
* </p>
*
* <p>
* This is functionally equivalent to the {@link Bean#dictionary()} annotation.
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='ja'>{@link Bean#dictionary()}
* <li class='jm'>{@link BeanContext.Builder#beanDictionary(Class...)}
* </ul>
*
* @param on The class that the dictionary values apply to.
* @param values
* The new values for this setting.
* @return This object.
*/
@FluentSetter
public Builder dictionaryOn(Class<?> on, Class<?>...values) {
bcBuilder.dictionaryOn(on, values);
return this;
}
/**
* POJO example.
*
* <p>
* Specifies an example of the specified class.
*
* <p>
* Examples are used in cases such as POJO examples in Swagger documents.
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// Create a serializer that excludes the 'foo' and 'bar' properties on the MyBean class.</jc>
* WriterSerializer <jv>serializer</jv> = JsonSerializer
* .<jsm>create</jsm>()
* .example(MyBean.<jk>class</jk>, <jk>new</jk> MyBean().setFoo(<js>"foo"</js>).setBar(123))
* .build();
* </p>
*
* <p>
* This is a shorthand method for the following code:
* <p class='bjava'>
* <jv>builder</jv>.annotations(MarshalledAnnotation.<jsm>create</jsm>(<jv>pojoClass</jv>).example(Json5.<jsf>DEFAULT</jsf>.toString(<jv>object</jv>)).build())
* </p>
*
* <h5 class='section'>Notes:</h5><ul>
* <li class='note'>Using this method assumes the serialized form of the object is the same as that produced
* by the default serializer. This may not be true based on settings or swaps on the constructed serializer.
* </ul>
*
* <p>
* POJO examples can also be defined on classes via the following:
* <ul class='spaced-list'>
* <li>The {@link Marshalled#example()} annotation on the class itself.
* <li>A static field annotated with {@link Example @Example}.
* <li>A static method annotated with {@link Example @Example} with zero arguments or one {@link BeanSession} argument.
* <li>A static method with name <c>example</c> with no arguments or one {@link BeanSession} argument.
* </ul>
*
* @param <T> The POJO class.
* @param pojoClass The POJO class.
* @param o
* An instance of the POJO class used for examples.
* @return This object.
*/
@FluentSetter
public <T> Builder example(Class<T> pojoClass, T o) {
bcBuilder.example(pojoClass, o);
return this;
}
/**
* POJO example.
*
* <p>
* Specifies an example in JSON of the specified class.
*
* <p>
* Examples are used in cases such as POJO examples in Swagger documents.
*
* <p>
* Setting applies to specified class and all subclasses.
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// Create a serializer that excludes the 'foo' and 'bar' properties on the MyBean class.</jc>
* WriterSerializer <jv>serializer</jv> = JsonSerializer
* .<jsm>create</jsm>()
* .example(MyBean.<jk>class</jk>, <js>"{foo:'bar'}"</js>)
* .build();
* </p>
*
* <p>
* This is a shorthand method for the following code:
* <p class='bjava'>
* <jv>builder</jv>.annotations(MarshalledAnnotation.<jsm>create</jsm>(<jv>pojoClass</jv>).example(<jv>json</jv>).build())
* </p>
*
* <p>
* POJO examples can also be defined on classes via the following:
* <ul class='spaced-list'>
* <li>A static field annotated with {@link Example @Example}.
* <li>A static method annotated with {@link Example @Example} with zero arguments or one {@link BeanSession} argument.
* <li>A static method with name <c>example</c> with no arguments or one {@link BeanSession} argument.
* </ul>
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='ja'>{@link Marshalled#example()}
* </ul>
*
* @param <T> The POJO class type.
* @param pojoClass The POJO class.
* @param json The JSON 5 representation of the example.
* @return This object.
*/
@FluentSetter
public <T> Builder example(Class<T> pojoClass, String json) {
bcBuilder.example(pojoClass, json);
return this;
}
/**
* Find fluent setters.
*
* <p>
* When enabled, fluent setters are detected on beans during parsing.
*
* <p>
* Fluent setters must have the following attributes:
* <ul>
* <li>Public.
* <li>Not static.
* <li>Take in one parameter.
* <li>Return the bean itself.
* </ul>
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// A bean with a fluent setter.</jc>
* <jk>public class</jk> MyBean {
* <jk>public</jk> MyBean foo(String <jv>value</jv>) {...}
* }
*
* <jc>// Create a parser that finds fluent setters.</jc>
* ReaderParser <jv>parser</jv> = JsonParser
* .<jsm>create</jsm>()
* .findFluentSetters()
* .build();
*
* <jc>// Parse into bean using fluent setter.</jc>
* MyBean <jv>bean</jv> = <jv>parser</jv>.parse(<js>"{foo:'bar'}"</js>, MyBean.<jk>class</jk>);
* </p>
*
* <h5 class='section'>Notes:</h5><ul>
* <li class='note'>The {@link Beanp @Beanp} annotation can also be used on methods to individually identify them as fluent setters.
* <li class='note'>The {@link Bean#findFluentSetters() @Bean.fluentSetters()} annotation can also be used on classes to specify to look for fluent setters.
* </ul>
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='ja'>{@link Bean#findFluentSetters()}
* <li class='ja'>{@link BeanConfig#findFluentSetters()}
* <li class='jm'>{@link BeanContext.Builder#findFluentSetters()}
* </ul>
*
* @return This object.
*/
@FluentSetter
public Builder findFluentSetters() {
bcBuilder.findFluentSetters();
return this;
}
/**
* Find fluent setters.
*
* <p>
* Identical to {@link #findFluentSetters()} but enables it on a specific class only.
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// A bean with a fluent setter.</jc>
* <jk>public class</jk> MyBean {
* <jk>public</jk> MyBean foo(String <jv>value</jv>) {...}
* }
*
* <jc>// Create a parser that finds fluent setters.</jc>
* ReaderParser <jv>parser</jv> = JsonParser
* .<jsm>create</jsm>()
* .findFluentSetters(MyBean.<jk>class</jk>)
* .build();
*
* <jc>// Parse into bean using fluent setter.</jc>
* MyBean <jv>bean</jv> = <jv>parser</jv>.parse(<js>"{foo:'bar'}"</js>, MyBean.<jk>class</jk>);
* </p>
*
* <h5 class='section'>Notes:</h5><ul>
* <li class='note'>This method is functionally equivalent to using the {@link Bean#findFluentSetters()} annotation.
* </ul>
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='ja'>{@link Bean#findFluentSetters()}
* <li class='jm'>{@link BeanContext.Builder#findFluentSetters()}
* </ul>
*
* @param on The class that this applies to.
* @return This object.
*/
@FluentSetter
public Builder findFluentSetters(Class<?> on) {
bcBuilder.findFluentSetters(on);
return this;
}
/**
* Ignore invocation errors on getters.
*
* <p>
* When enabled, errors thrown when calling bean getter methods will silently be ignored.
* Otherwise, a {@code BeanRuntimeException} is thrown.
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// A bean with a property that throws an exception.</jc>
* <jk>public class</jk> MyBean {
* <jk>public</jk> String getFoo() {
* <jk>throw new</jk> RuntimeException(<js>"foo"</js>);
* }
* }
*
* <jc>// Create a serializer that ignores bean getter exceptions.</jc>
* WriterSerializer <jv>serializer</jv> = JsonSerializer
* .<jsm>create</jsm>()
* .ingoreInvocationExceptionsOnGetters()
* .build();
*
* <jc>// Exception is ignored.</jc>
* String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
* </p>
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='ja'>{@link BeanConfig#ignoreInvocationExceptionsOnGetters()}
* <li class='jm'>{@link BeanContext.Builder#ignoreInvocationExceptionsOnGetters()}
* </ul>
*
* @return This object.
*/
@FluentSetter
public Builder ignoreInvocationExceptionsOnGetters() {
bcBuilder.ignoreInvocationExceptionsOnGetters();
return this;
}
/**
* Ignore invocation errors on setters.
*
* <p>
* When enabled, errors thrown when calling bean setter methods will silently be ignored.
* Otherwise, a {@code BeanRuntimeException} is thrown.
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// A bean with a property that throws an exception.</jc>
* <jk>public class</jk> MyBean {
* <jk>public void</jk> setFoo(String <jv>foo</jv>) {
* <jk>throw new</jk> RuntimeException(<js>"foo"</js>);
* }
* }
*
* <jc>// Create a parser that ignores bean setter exceptions.</jc>
* ReaderParser <jv>parser</jv> = JsonParser
* .<jsm>create</jsm>()
* .ignoreInvocationExceptionsOnSetters()
* .build();
*
* <jc>// Exception is ignored.</jc>
* MyBean <jv>bean</jv> = <jv>parser</jv>.parse(<js>"{foo:'bar'}"</js>, MyBean.<jk>class</jk>);
* </p>
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='ja'>{@link BeanConfig#ignoreInvocationExceptionsOnSetters()}
* <li class='jm'>{@link BeanContext.Builder#ignoreInvocationExceptionsOnSetters()}
* </ul>
*
* @return This object.
*/
@FluentSetter
public Builder ignoreInvocationExceptionsOnSetters() {
bcBuilder.ignoreInvocationExceptionsOnSetters();
return this;
}
/**
* Don't silently ignore missing setters.
*
* <p>
* When enabled, trying to set a value on a bean property without a setter will throw a {@link BeanRuntimeException}.
* Otherwise, it will be silently ignored.
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// A bean with a property with a getter but not a setter.</jc>
* <jk>public class</jk> MyBean {
* <jk>public void</jk> getFoo() {
* <jk>return</jk> <js>"foo"</js>;
* }
* }
*
* <jc>// Create a parser that throws an exception if a setter is not found but a getter is.</jc>
* ReaderParser <jv>parser</jv> = JsonParser
* .<jsm>create</jsm>()
* .disableIgnoreMissingSetters()
* .build();
*
* <jc>// Throws a ParseException.</jc>
* MyBean <jv>bean</jv> = <jv>parser</jv>.parse(<js>"{foo:'bar'}"</js>, MyBean.<jk>class</jk>);
* </p>
*
* <h5 class='section'>Notes:</h5><ul>
* <li class='note'>The {@link BeanIgnore @BeanIgnore} annotation can also be used on getters and fields to ignore them.
* </ul>
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='ja'>{@link BeanConfig#disableIgnoreMissingSetters()}
* <li class='jm'>{@link BeanContext.Builder#disableIgnoreMissingSetters()}
* </ul>
*
* @return This object.
*/
@FluentSetter
public Builder disableIgnoreMissingSetters() {
bcBuilder.disableIgnoreMissingSetters();
return this;
}
/**
* Don't ignore transient fields.
*
* <p>
* When enabled, methods and fields marked as <jk>transient</jk> will not be ignored as bean properties.
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// A bean with a transient field.</jc>
* <jk>public class</jk> MyBean {
* <jk>public transient</jk> String <jf>foo</jf> = <js>"foo"</js>;
* }
*
* <jc>// Create a serializer that doesn't ignore transient fields.</jc>
* WriterSerializer <jv>serializer</jv> = JsonSerializer
* .<jsm>create</jsm>()
* .disableIgnoreTransientFields()
* .build();
*
* <jc>// Produces: {"foo":"foo"}</jc>
* String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
* </p>
*
* <h5 class='section'>Notes:</h5><ul>
* <li class='note'>The {@link Beanp @Beanp} annotation can also be used on transient fields to keep them from being ignored.
* </ul>
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='ja'>{@link BeanConfig#disableIgnoreTransientFields()}
* <li class='jm'>{@link BeanContext.Builder#disableIgnoreTransientFields()}
* </ul>
*
* @return This object.
*/
@FluentSetter
public Builder disableIgnoreTransientFields() {
bcBuilder.disableIgnoreTransientFields();
return this;
}
/**
* Ignore unknown properties.
*
* <p>
* When enabled, trying to set a value on a non-existent bean property will silently be ignored.
* Otherwise, a {@code BeanRuntimeException} is thrown.
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// A bean with a single property.</jc>
* <jk>public class</jk> MyBean {
* <jk>public</jk> String <jf>foo</jf>;
* }
*
* <jc>// Create a parser that ignores missing bean properties.</jc>
* ReaderParser <jv>parser</jv> = JsonParser
* .<jsm>create</jsm>()
* .ignoreUnknownBeanProperties()
* .build();
*
* <jc>// Doesn't throw an exception on unknown 'bar' property.</jc>
* MyBean <jv>bean</jv> = <jv>parser</jv>.parse(<js>"{foo:'foo',bar:'bar'}"</js>, MyBean.<jk>class</jk>);
* </p>
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='ja'>{@link BeanConfig#ignoreUnknownBeanProperties()}
* <li class='jm'>{@link BeanContext.Builder#ignoreUnknownBeanProperties()}
* </ul>
*
* @return This object.
*/
@FluentSetter
public Builder ignoreUnknownBeanProperties() {
bcBuilder.ignoreUnknownBeanProperties();
return this;
}
/**
* Ignore unknown enum values.
*
* <p>
* When enabled, unknown enum values are set to <jk>null</jk> instead of throwing a parse exception.
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='ja'>{@link BeanConfig#ignoreUnknownEnumValues()}
* <li class='jm'>{@link BeanContext.Builder#ignoreUnknownEnumValues()}
* </ul>
*
* @return This object.
*/
@FluentSetter
public Builder ignoreUnknownEnumValues() {
bcBuilder.ignoreUnknownEnumValues();
return this;
}
/**
* Don't ignore unknown properties with null values.
*
* <p>
* When enabled, trying to set a <jk>null</jk> value on a non-existent bean property will throw a {@link BeanRuntimeException}.
* Otherwise it will be silently ignored.
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// A bean with a single property.</jc>
* <jk>public class</jk> MyBean {
* <jk>public</jk> String <jf>foo</jf>;
* }
*
* <jc>// Create a parser that throws an exception on an unknown property even if the value being set is null.</jc>
* ReaderParser <jv>parser</jv> = JsonParser
* .<jsm>create</jsm>()
* .disableIgnoreUnknownNullBeanProperties()
* .build();
*
* <jc>// Throws a BeanRuntimeException wrapped in a ParseException on the unknown 'bar' property.</jc>
* MyBean <jv>bean</jv> = <jv>parser</jv>.parse(<js>"{foo:'foo',bar:null}"</js>, MyBean.<jk>class</jk>);
* </p>
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='ja'>{@link BeanConfig#disableIgnoreUnknownNullBeanProperties()}
* <li class='jm'>{@link BeanContext.Builder#disableIgnoreUnknownNullBeanProperties()}
* </ul>
*
* @return This object.
*/
@FluentSetter
public Builder disableIgnoreUnknownNullBeanProperties() {
bcBuilder.disableIgnoreUnknownNullBeanProperties();
return this;
}
/**
* Implementation classes.
*
* <p>
* For interfaces and abstract classes this method can be used to specify an implementation class for the
* interface/abstract class so that instances of the implementation class are used when instantiated (e.g. during a
* parse).
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// A bean interface.</jc>
* <jk>public interface</jk> MyBean {
* ...
* }
*
* <jc>// A bean implementation.</jc>
* <jk>public class</jk> MyBeanImpl <jk>implements</jk> MyBean {
* ...
* }
* <jc>// Create a parser that instantiates MyBeanImpls when parsing MyBeans.</jc>
* ReaderParser <jv>parser</jv> = JsonParser
* .<jsm>create</jsm>()
* .implClass(MyBean.<jk>class</jk>, MyBeanImpl.<jk>class</jk>)
* .build();
*
* <jc>// Instantiates a MyBeanImpl,</jc>
* MyBean <jv>bean</jv> = <jv>parser</jv>.parse(<js>"..."</js>, MyBean.<jk>class</jk>);
* </p>
*
* @param interfaceClass The interface class.
* @param implClass The implementation class.
* @return This object.
*/
@FluentSetter
public Builder implClass(Class<?> interfaceClass, Class<?> implClass) {
bcBuilder.implClass(interfaceClass, implClass);
return this;
}
/**
* Implementation classes.
*
* <p>
* For interfaces and abstract classes this method can be used to specify an implementation class for the
* interface/abstract class so that instances of the implementation class are used when instantiated (e.g. during a
* parse).
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// A bean with a single property.</jc>
* <jk>public interface</jk> MyBean {
* ...
* }
*
* <jc>// A bean with a single property.</jc>
* <jk>public class</jk> MyBeanImpl <jk>implements</jk> MyBean {
* ...
* }
* <jc>// Create a parser that instantiates MyBeanImpls when parsing MyBeans.</jc>
* ReaderParser <jv>parser</jv> = JsonParser
* .<jsm>create</jsm>()
* .implClasses(AMap.<jsm>of</jsm>(MyBean.<jk>class</jk>, MyBeanImpl.<jk>class</jk>))
* .build();
*
* <jc>// Instantiates a MyBeanImpl,</jc>
* MyBean <jv>bean</jv> = <jv>parser</jv>.parse(<js>"..."</js>, MyBean.<jk>class</jk>);
* </p>
*
* @param values
* The new value for this setting.
* @return This object.
*/
@FluentSetter
public Builder implClasses(Map<Class<?>,Class<?>> values) {
bcBuilder.implClasses(values);
return this;
}
/**
* Identifies a class to be used as the interface class for the specified class and all subclasses.
*
* <p>
* When specified, only the list of properties defined on the interface class will be used during serialization.
* Additional properties on subclasses will be ignored.
*
* <p class='bjava'>
* <jc>// Parent class or interface</jc>
* <jk>public abstract class</jk> A {
* <jk>public</jk> String <jf>foo</jf> = <js>"foo"</js>;
* }
*
* <jc>// Sub class</jc>
* <jk>public class</jk> A1 <jk>extends</jk> A {
* <jk>public</jk> String <jf>bar</jf> = <js>"bar"</js>;
* }
*
* <jc>// Create a serializer and define our interface class mapping.</jc>
* WriterSerializer <jv>serializer</jv> = JsonSerializer
* .<jsm>create</jsm>()
* .interfaceClass(A1.<jk>class</jk>, A.<jk>class</jk>)
* .build();
*
* <jc>// Produces "{"foo":"foo"}"</jc>
* String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> A1());
* </p>
*
* <p>
* This annotation can be used on the parent class so that it filters to all child classes, or can be set
* individually on the child classes.
*
* <h5 class='section'>Notes:</h5><ul>
* <li class='note'>The {@link Bean#interfaceClass() @Bean(interfaceClass)} annotation is the equivalent annotation-based solution.
* </ul>
*
* @param on The class that the interface class applies to.
* @param value
* The new value for this setting.
* @return This object.
*/
@FluentSetter
public Builder interfaceClass(Class<?> on, Class<?> value) {
bcBuilder.interfaceClass(on, value);
return this;
}
/**
* Identifies a set of interfaces.
*
* <p>
* When specified, only the list of properties defined on the interface class will be used during serialization
* of implementation classes. Additional properties on subclasses will be ignored.
*
* <p class='bjava'>
* <jc>// Parent class or interface</jc>
* <jk>public abstract class</jk> A {
* <jk>public</jk> String <jf>foo</jf> = <js>"foo"</js>;
* }
*
* <jc>// Sub class</jc>
* <jk>public class</jk> A1 <jk>extends</jk> A {
* <jk>public</jk> String <jf>bar</jf> = <js>"bar"</js>;
* }
*
* <jc>// Create a serializer and define our interface class mapping.</jc>
* WriterSerializer <jv>serializer</jv> = JsonSerializer
* .<jsm>create</jsm>()
* .interfaces(A.<jk>class</jk>)
* .build();
*
* <jc>// Produces "{"foo":"foo"}"</jc>
* String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> A1());
* </p>
*
* <p>
* This annotation can be used on the parent class so that it filters to all child classes, or can be set
* individually on the child classes.
*
* <h5 class='section'>Notes:</h5><ul>
* <li class='note'>The {@link Bean#interfaceClass() @Bean(interfaceClass)} annotation is the equivalent annotation-based solution.
* </ul>
*
* @param value
* The new value for this setting.
* @return This object.
*/
@FluentSetter
public Builder interfaces(Class<?>...value) {
bcBuilder.interfaces(value);
return this;
}
/**
* <i><l>Context</l> configuration property:&emsp;</i> Locale.
*
* <p>
* Specifies the default locale for serializer and parser sessions when not specified via {@link BeanSession.Builder#locale(Locale)}.
* Typically used for POJO swaps that need to deal with locales such as swaps that convert <l>Date</l> and <l>Calendar</l>
* objects to strings by accessing it via the session passed into the {@link ObjectSwap#swap(BeanSession, Object)} and
* {@link ObjectSwap#unswap(BeanSession, Object, ClassMeta, String)} methods.
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// Define a POJO swap that skips serializing beans if we're in the UK.</jc>
* <jk>public class</jk> MyBeanSwap <jk>extends</jk> StringSwap&lt;MyBean&gt; {
* <ja>@Override</ja>
* <jk>public</jk> String swap(BeanSession <jv>session</jv>, MyBean <jv>bean</jv>) <jk>throws</jk> Exception {
* <jk>if</jk> (<jv>session</jv>.getLocale().equals(Locale.<jsf>UK</jsf>))
* <jk>return null</jk>;
* <jk>return</jk> <jv>bean</jv>.toString();
* }
* }
*
* <jc>// Create a serializer that uses the specified locale if it's not passed in through session args.</jc>
* WriterSerializer <jv>serializer</jv> = JsonSerializer
* .<jsm>create</jsm>()
* .locale(Locale.<jsf>UK</jsf>)
* .swaps(MyBeanSwap.<jk>class</jk>)
* .build();
* </p>
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='ja'>{@link BeanConfig#locale()}
* <li class='jm'>{@link BeanContext.Builder#locale(Locale)}
* <li class='jm'>{@link BeanSession.Builder#locale(Locale)}
* </ul>
*
* @param value The new value for this property.
* @return This object.
*/
@FluentSetter
public Builder locale(Locale value) {
bcBuilder.locale(value);
return this;
}
/**
* <i><l>Context</l> configuration property:&emsp;</i> Media type.
*
* <p>
* Specifies the default media type for serializer and parser sessions when not specified via {@link BeanSession.Builder#mediaType(MediaType)}.
* Typically used for POJO swaps that need to serialize the same POJO classes differently depending on
* the specific requested media type. For example, a swap could handle a request for media types <js>"application/json"</js>
* and <js>"application/json+foo"</js> slightly differently even though they're both being handled by the same JSON
* serializer or parser.
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// Define a POJO swap that skips serializing beans if the media type is application/json.</jc>
* <jk>public class</jk> MyBeanSwap <jk>extends</jk> StringSwap&lt;MyBean&gt; {
* <ja>@Override</ja>
* <jk>public</jk> String swap(BeanSession <jv>session</jv>, MyBean <jv>bean</jv>) <jk>throws</jk> Exception {
* <jk>if</jk> (<jv>session</jv>.getMediaType().equals(<js>"application/json"</js>))
* <jk>return null</jk>;
* <jk>return</jk> <jv>bean</jv>.toString();
* }
* }
*
* <jc>// Create a serializer that uses the specified media type if it's not passed in through session args.</jc>
* WriterSerializer <jv>serializer</jv> = JsonSerializer
* .<jsm>create</jsm>()
* .mediaType(MediaType.<jsf>JSON</jsf>)
* .build();
* </p>
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='ja'>{@link BeanConfig#mediaType()}
* <li class='jm'>{@link BeanContext.Builder#mediaType(MediaType)}
* <li class='jm'>{@link BeanSession.Builder#mediaType(MediaType)}
* </ul>
*
* @param value The new value for this property.
* @return This object.
*/
@FluentSetter
public Builder mediaType(MediaType value) {
bcBuilder.mediaType(value);
return this;
}
/**
* Bean class exclusions.
*
* <p>
* List of classes that should not be treated as beans even if they appear to be bean-like.
* Not-bean classes are converted to <c>Strings</c> during serialization.
*
* <p>
* Values can consist of any of the following types:
* <ul>
* <li>Classes.
* <li>Arrays and collections of classes.
* </ul>
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// A bean with a single property.</jc>
* <jk>public class</jk> MyBean {
* <jk>public</jk> String <jf>foo</jf> = <js>"bar"</js>;
*
* <jk>public</jk> String toString() {
* <jk>return</jk> <js>"baz"</js>;
* }
* }
*
* <jc>// Create a serializer that doesn't treat MyBean as a bean class.</jc>
* WriterSerializer <jv>serializer</jv> = JsonSerializer
* .<jsm>create</jsm>()
* .notBeanClasses(MyBean.<jk>class</jk>)
* .build();
*
* <jc>// Produces "baz" instead of {"foo":"bar"}</jc>
* String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
* </p>
*
* <h5 class='section'>Notes:</h5><ul>
* <li class='note'>The {@link BeanIgnore @BeanIgnore} annotation can also be used on classes to prevent them from being recognized as beans.
* </ul>
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='ja'>{@link BeanIgnore}
* <li class='ja'>{@link BeanConfig#notBeanClasses()}
* <li class='jf'>{@link BeanContext.Builder#notBeanClasses()}
* </ul>
*
* @param values
* The values to add to this setting.
* <br>Values can consist of any of the following types:
* <ul>
* <li>Classes.
* <li>Arrays and collections of classes.
* </ul>
* @return This object.
*/
@FluentSetter
public Builder notBeanClasses(Class<?>...values) {
bcBuilder.notBeanClasses(values);
return this;
}
/**
* Bean package exclusions.
*
* <p>
* Used as a convenient way of defining the {@link BeanContext.Builder#notBeanClasses(Class...)} property for entire packages.
* Any classes within these packages will be serialized to strings using {@link Object#toString()}.
*
* <p>
* Note that you can specify suffix patterns to include all subpackages.
*
* <p>
* Values can consist of any of the following types:
* <ul>
* <li>Strings.
* <li>Arrays and collections of strings.
* </ul>
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// Create a serializer that ignores beans in the specified packages.</jc>
* WriterSerializer <jv>serializer</jv> = JsonSerializer
* .<jsm>create</jsm>()
* .notBeanPackages(<js>"org.apache.foo"</js>, <js>"org.apache.bar.*"</js>)
* .build();
* </p>
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='jm'>{@link BeanContext.Builder#notBeanPackages(String...)}
* </ul>
*
* @param values
* The values to add to this setting.
* <br>Values can consist of any of the following types:
* <ul>
* <li>{@link Package} objects.
* <li>Strings.
* <li>Arrays and collections of anything in this list.
* </ul>
* @return This object.
*/
@FluentSetter
public Builder notBeanPackages(String...values) {
bcBuilder.notBeanPackages(values);
return this;
}
/**
* Bean property namer
*
* <p>
* The class to use for calculating bean property names.
*
* <p>
* Predefined classes:
* <ul>
* <li>{@link BasicPropertyNamer} - Default.
* <li>{@link PropertyNamerDLC} - Dashed-lower-case names.
* <li>{@link PropertyNamerULC} - Dashed-upper-case names.
* </ul>
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// A bean with a single property.</jc>
* <jk>public class</jk> MyBean {
* <jk>public</jk> String <jf>fooBarBaz</jf> = <js>"fooBarBaz"</js>;
* }
*
* <jc>// Create a serializer that uses Dashed-Lower-Case property names.</jc>
* <jc>// (e.g. "foo-bar-baz" instead of "fooBarBaz")</jc>
* WriterSerializer <jv>serializer</jv> = JsonSerializer
* .<jsm>create</jsm>()
* .propertyNamer(PropertyNamerDLC.<jk>class</jk>)
* .build();
*
* <jc>// Produces: {"foo-bar-baz":"fooBarBaz"}</jc>
* String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
* </p>
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='jm'>{@link BeanContext.Builder#propertyNamer(Class)}
* </ul>
*
* @param value
* The new value for this setting.
* <br>The default is {@link BasicPropertyNamer}.
* @return This object.
*/
@FluentSetter
public Builder propertyNamer(Class<? extends PropertyNamer> value) {
bcBuilder.propertyNamer(value);
return this;
}
/**
* Bean property namer
*
* <p>
* Same as {@link #propertyNamer(Class)} but allows you to specify a namer for a specific class.
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// A bean with a single property.</jc>
* <jk>public class</jk> MyBean {
* <jk>public</jk> String <jf>fooBarBaz</jf> = <js>"fooBarBaz"</js>;
* }
*
* <jc>// Create a serializer that uses Dashed-Lower-Case property names for the MyBean class only.</jc>
* <jc>// (e.g. "foo-bar-baz" instead of "fooBarBaz")</jc>
* WriterSerializer <jv>serializer</jv> = JsonSerializer
* .<jsm>create</jsm>()
* .propertyNamer(MyBean.<jk>class</jk>, PropertyNamerDLC.<jk>class</jk>)
* .build();
*
* <jc>// Produces: {"foo-bar-baz":"fooBarBaz"}</jc>
* String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
* </p>
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='ja'>{@link Bean#propertyNamer() Bean(propertyNamer)}
* <li class='jm'>{@link BeanContext.Builder#propertyNamer(Class)}
* </ul>
*
* @param on The class that the namer applies to.
* @param value
* The new value for this setting.
* <br>The default is {@link BasicPropertyNamer}.
* @return This object.
*/
@FluentSetter
public Builder propertyNamer(Class<?> on, Class<? extends PropertyNamer> value) {
bcBuilder.propertyNamer(on, value);
return this;
}
/**
* Sort bean properties.
*
* <p>
* When enabled, all bean properties will be serialized and access in alphabetical order.
* Otherwise, the natural order of the bean properties is used which is dependent on the JVM vendor.
* On IBM JVMs, the bean properties are ordered based on their ordering in the Java file.
* On Oracle JVMs, the bean properties are not ordered (which follows the official JVM specs).
*
* <p>
* this setting is disabled by default so that IBM JVM users don't have to use {@link Bean @Bean} annotations
* to force bean properties to be in a particular order and can just alter the order of the fields/methods
* in the Java file.
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// A bean with 3 properties.</jc>
* <jk>public class</jk> MyBean {
* <jk>public</jk> String <jf>c</jf> = <js>"1"</js>;
* <jk>public</jk> String <jf>b</jf> = <js>"2"</js>;
* <jk>public</jk> String <jf>a</jf> = <js>"3"</js>;
* }
*
* <jc>// Create a serializer that sorts bean properties.</jc>
* WriterSerializer <jv>serializer</jv> = JsonSerializer
* .<jsm>create</jsm>()
* .sortProperties()
* .build();
*
* <jc>// Produces: {"a":"3","b":"2","c":"1"}</jc>
* String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
* </p>
*
* <h5 class='section'>Notes:</h5><ul>
* <li class='note'>The {@link Bean#sort() @Bean.sort()} annotation can also be used to sort properties on just a single class.
* </ul>
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='jm'>{@link BeanContext.Builder#sortProperties()}
* </ul>
*
* @return This object.
*/
@FluentSetter
public Builder sortProperties() {
bcBuilder.sortProperties();
return this;
}
/**
* Sort bean properties.
*
* <p>
* Same as {@link #sortProperties()} but allows you to specify individual bean classes instead of globally.
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// A bean with 3 properties.</jc>
* <jk>public class</jk> MyBean {
* <jk>public</jk> String <jf>c</jf> = <js>"1"</js>;
* <jk>public</jk> String <jf>b</jf> = <js>"2"</js>;
* <jk>public</jk> String <jf>a</jf> = <js>"3"</js>;
* }
*
* <jc>// Create a serializer that sorts properties on MyBean.</jc>
* WriterSerializer <jv>serializer</jv> = JsonSerializer
* .<jsm>create</jsm>()
* .sortProperties(MyBean.<jk>class</jk>)
* .build();
*
* <jc>// Produces: {"a":"3","b":"2","c":"1"}</jc>
* String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
* </p>
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='ja'>{@link Bean#sort() Bean(sort)}
* <li class='jm'>{@link BeanContext.Builder#sortProperties()}
* </ul>
*
* @param on The bean classes to sort properties on.
* @return This object.
*/
@FluentSetter
public Builder sortProperties(Class<?>...on) {
bcBuilder.sortProperties(on);
return this;
}
/**
* Identifies a stop class for the annotated class.
*
* <p>
* Identical in purpose to the stop class specified by {@link Introspector#getBeanInfo(Class, Class)}.
* Any properties in the stop class or in its base classes will be ignored during analysis.
*
* <p>
* For example, in the following class hierarchy, instances of <c>C3</c> will include property <c>p3</c>,
* but not <c>p1</c> or <c>p2</c>.
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jk>public class</jk> C1 {
* <jk>public int</jk> getP1();
* }
*
* <jk>public class</jk> C2 <jk>extends</jk> C1 {
* <jk>public int</jk> getP2();
* }
*
* <jk>public class</jk> C3 <jk>extends</jk> C2 {
* <jk>public int</jk> getP3();
* }
*
* <jc>// Create a serializer specifies a stop class for C3.</jc>
* WriterSerializer <jv>serializer</jv> = JsonSerializer
* .<jsm>create</jsm>()
* .stopClass(C3.<jk>class</jk>, C2.<jk>class</jk>)
* .build();
*
* <jc>// Produces: {"p3":"..."}</jc>
* String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> C3());
* </p>
*
* @param on The class on which the stop class is being applied.
* @param value
* The new value for this setting.
* @return This object.
*/
@FluentSetter
public Builder stopClass(Class<?> on, Class<?> value) {
bcBuilder.stopClass(on, value);
return this;
}
/**
* Java object swaps.
*
* <p>
* Swaps are used to "swap out" non-serializable classes with serializable equivalents during serialization,
* and "swap in" the non-serializable class during parsing.
*
* <p>
* An example of a swap would be a <c>Calendar</c> object that gets swapped out for an ISO8601 string.
*
* <p>
* Multiple swaps can be associated with a single class.
* When multiple swaps are applicable to the same class, the media type pattern defined by
* {@link ObjectSwap#forMediaTypes()} or {@link Swap#mediaTypes() @Swap(mediaTypes)} are used to come up with the best match.
*
* <p>
* Values can consist of any of the following types:
* <ul>
* <li>Any subclass of {@link ObjectSwap}.
* <li>Any instance of {@link ObjectSwap}.
* <li>Any surrogate class. A shortcut for defining a {@link SurrogateSwap}.
* <li>Any array or collection of the objects above.
* </ul>
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// Sample swap for converting Dates to ISO8601 strings.</jc>
* <jk>public class</jk> MyDateSwap <jk>extends</jk> StringSwap&lt;Date&gt; {
* <jc>// ISO8601 formatter.</jc>
* <jk>private</jk> DateFormat <jf>format</jf> = <jk>new</jk> SimpleDateFormat(<js>"yyyy-MM-dd'T'HH:mm:ssZ"</js>);
*
* <ja>@Override</ja>
* <jk>public</jk> String swap(BeanSession <jv>session</jv>, Date <jv>date</jv>) {
* <jk>return</jk> <jf>format</jf>.format(<jv>date</jv>);
* }
*
* <ja>@Override</ja>
* <jk>public</jk> Date unswap(BeanSession <jv>session</jv>, String <jv>string</jv>, ClassMeta <jv>hint</jv>) <jk>throws</jk> Exception {
* <jk>return</jk> <jf>format</jf>.parse(<jv>string</jv>);
* }
* }
*
* <jc>// Sample bean with a Date field.</jc>
* <jk>public class</jk> MyBean {
* <jk>public</jk> Date <jf>date</jf> = <jk>new</jk> Date(112, 2, 3, 4, 5, 6);
* }
*
* <jc>// Create a serializer that uses our date swap.</jc>
* WriterSerializer <jv>serializer</jv> = JsonSerializer
* .<jsm>create</jsm>()
* .swaps(MyDateSwap.<jk>class</jk>)
* .build();
*
* <jc>// Produces: {"date":"2012-03-03T04:05:06-0500"}</jc>
* String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
*
* <jc>// Create a serializer that uses our date swap.</jc>
* ReaderParser <jv>parser</jv> = JsonParser
* .<jsm>create</jsm>()
* .swaps(MyDateSwap.<jk>class</jk>)
* .build();
*
* <jc>// Use our parser to parse a bean.</jc>
* MyBean <jv>bean</jv> = <jv>parser</jv>.parse(<jv>json</jv>, MyBean.<jk>class</jk>);
* </p>
*
* <h5 class='section'>Notes:</h5><ul>
* <li class='note'>The {@link Swap @Swap} annotation can also be used on classes to identify swaps for the class.
* <li class='note'>The {@link Swap @Swap} annotation can also be used on bean methods and fields to identify swaps for values of those bean properties.
* </ul>
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='jf'>{@link BeanContext.Builder#swaps(Class...)}
* </ul>
*
* @param values
* The values to add to this setting.
* <br>Values can consist of any of the following types:
* <ul>
* <li>Any subclass of {@link ObjectSwap}.
* <li>Any surrogate class. A shortcut for defining a {@link SurrogateSwap}.
* <li>Any array or collection of the objects above.
* </ul>
* @return This object.
*/
@FluentSetter
public Builder swaps(Class<?>...values) {
bcBuilder.swaps(values);
return this;
}
/**
* A shortcut for defining a {@link FunctionalSwap}.
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// Create a serializer that performs a custom format for Date objects.</jc>
* WriterSerializer <jv>serializer</jv> = JsonSerializer
* .<jsm>create</jsm>()
* .swap(Date.<jk>class</jk>, String.<jk>class</jk>, <jv>x</jv> -&gt; <jsm>format</jsm>(<jv>x</jv>))
* .build();
* </p>
*
* @param <T> The object type being swapped out.
* @param <S> The object type being swapped in.
* @param normalClass The object type being swapped out.
* @param swappedClass The object type being swapped in.
* @param swapFunction The function to convert the object.
* @return This object.
*/
@FluentSetter
public <T,S> Builder swap(Class<T> normalClass, Class<S> swappedClass, ThrowingFunction<T,S> swapFunction) {
bcBuilder.swap(normalClass, swappedClass, swapFunction);
return this;
}
/**
* A shortcut for defining a {@link FunctionalSwap}.
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// Create a serializer that performs a custom format for Date objects.</jc>
* WriterSerializer <jv>serializer</jv> = JsonSerializer
* .<jsm>create</jsm>()
* .swap(Date.<jk>class</jk>, String.<jk>class</jk>, <jv>x</jv> -&gt; <jsm>format</jsm>(<jv>x</jv>), <jv>x</jv> -&gt; <jsm>parse</jsm>(<jv>x</jv>))
* .build();
* </p>
*
* @param <T> The object type being swapped out.
* @param <S> The object type being swapped in.
* @param normalClass The object type being swapped out.
* @param swappedClass The object type being swapped in.
* @param swapFunction The function to convert the object during serialization.
* @param unswapFunction The function to convert the object during parsing.
* @return This object.
*/
@FluentSetter
public <T,S> Builder swap(Class<T> normalClass, Class<S> swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> unswapFunction) {
bcBuilder.swap(normalClass, swappedClass, swapFunction, unswapFunction);
return this;
}
/**
* <i><l>Context</l> configuration property:&emsp;</i> TimeZone.
*
* <p>
* Specifies the default time zone for serializer and parser sessions when not specified via {@link BeanSession.Builder#timeZone(TimeZone)}.
* Typically used for POJO swaps that need to deal with timezones such as swaps that convert <l>Date</l> and <l>Calendar</l>
* objects to strings by accessing it via the session passed into the {@link ObjectSwap#swap(BeanSession, Object)} and
* {@link ObjectSwap#unswap(BeanSession, Object, ClassMeta, String)} methods.
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// Define a POJO swap that skips serializing beans if the time zone is GMT.</jc>
* <jk>public class</jk> MyBeanSwap <jk>extends</jk> StringSwap&lt;MyBean&gt; {
* <ja>@Override</ja>
* <jk>public</jk> String swap(BeanSession <jv>session</jv>, MyBean <jv>bean</jv>) <jk>throws</jk> Exception {
* <jk>if</jk> (<jv>session</jv>.getTimeZone().equals(TimeZone.<jsf>GMT</jsf>))
* <jk>return null</jk>;
* <jk>return</jk> <jv>bean</jv>.toString();
* }
* }
*
* <jc>// Create a serializer that uses GMT if the timezone is not specified in the session args.</jc>
* WriterSerializer <jv>serializer</jv> = JsonSerializer
* .<jsm>create</jsm>()
* .timeZone(TimeZone.<jsf>GMT</jsf>)
* .build();
* </p>
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='ja'>{@link BeanConfig#timeZone()}
* <li class='jm'>{@link BeanContext.Builder#timeZone(TimeZone)}
* <li class='jm'>{@link BeanSession.Builder#timeZone(TimeZone)}
* </ul>
*
* @param value The new value for this property.
* @return This object.
*/
@FluentSetter
public Builder timeZone(TimeZone value) {
bcBuilder.timeZone(value);
return this;
}
/**
* An identifying name for this class.
*
* <p>
* The name is used to identify the class type during parsing when it cannot be inferred through reflection.
* For example, if a bean property is of type <c>Object</c>, then the serializer will add the name to the
* output so that the class can be determined during parsing.
*
* <p>
* It is also used to specify element names in XML.
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// Use _type='mybean' to identify this bean.</jc>
* <jk>public class</jk> MyBean {...}
*
* <jc>// Create a serializer and specify the type name..</jc>
* WriterSerializer <jv>serializer</jv> = JsonSerializer
* .<jsm>create</jsm>()
* .typeName(MyBean.<jk>class</jk>, <js>"mybean"</js>)
* .build();
*
* <jc>// Produces: {"_type":"mybean",...}</jc>
* String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
* </p>
*
* <h5 class='section'>Notes:</h5><ul>
* <li class='note'>Equivalent to the {@link Bean#typeName() Bean(typeName)} annotation.
* </ul>
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='jc'>{@link Bean#typeName() Bean(typeName)}
* <li class='jm'>{@link BeanContext.Builder#beanDictionary(Class...)}
* </ul>
*
* @param on
* The class the type name is being defined on.
* @param value
* The new value for this setting.
* @return This object.
*/
@FluentSetter
public Builder typeName(Class<?> on, String value) {
bcBuilder.typeName(on, value);
return this;
}
/**
* Bean type property name.
*
* <p>
* This specifies the name of the bean property used to store the dictionary name of a bean type so that the
* parser knows the data type to reconstruct.
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// POJOs with @Bean(name) annotations.</jc>
* <ja>@Bean</ja>(typeName=<js>"foo"</js>)
* <jk>public class</jk> Foo {...}
* <ja>@Bean</ja>(typeName=<js>"bar"</js>)
* <jk>public class</jk> Bar {...}
*
* <jc>// Create a serializer that uses 't' instead of '_type' for dictionary names.</jc>
* WriterSerializer <jv>serializer</jv> = JsonSerializer
* .<jsm>create</jsm>()
* .typePropertyName(<js>"t"</js>)
* .dictionary(Foo.<jk>class</jk>, Bar.<jk>class</jk>)
* .build();
*
* <jc>// Create a serializer that uses 't' instead of '_type' for dictionary names.</jc>
* ReaderParser <jv>parser</jv> = JsonParser
* .<jsm>create</jsm>()
* .typePropertyName(<js>"t"</js>)
* .dictionary(Foo.<jk>class</jk>, Bar.<jk>class</jk>)
* .build();
*
* <jc>// A bean with a field with an indeterminate type.</jc>
* <jk>public class</jk> MyBean {
* <jk>public</jk> Object <jf>mySimpleField</jf>;
* }
*
* <jc>// Produces "{mySimpleField:{t:'foo',...}}".</jc>
* String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
*
* <jc>// Parse bean.</jc>
* MyBean <jv>bean</jv> = <jv>parser</jv>.parse(<jv>json</jv>, MyBean.<jk>class</jk>);
* </p>
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='ja'>{@link Bean#typePropertyName()}
* <li class='ja'>{@link BeanConfig#typePropertyName()}
* <li class='jm'>{@link BeanContext.Builder#typePropertyName(String)}
* </ul>
*
* @param value
* The new value for this setting.
* <br>The default is <js>"_type"</js>.
* @return This object.
*/
@FluentSetter
public Builder typePropertyName(String value) {
bcBuilder.typePropertyName(value);
return this;
}
/**
* Bean type property name.
*
* <p>
* Same as {@link #typePropertyName(String)} except targets a specific bean class instead of globally.
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// POJOs with @Bean(name) annotations.</jc>
* <ja>@Bean</ja>(typeName=<js>"foo"</js>)
* <jk>public class</jk> Foo {...}
* <ja>@Bean</ja>(typeName=<js>"bar"</js>)
* <jk>public class</jk> Bar {...}
*
* <jc>// A bean with a field with an indeterminate type.</jc>
* <jk>public class</jk> MyBean {
* <jk>public</jk> Object <jf>mySimpleField</jf>;
* }
*
* <jc>// Create a serializer that uses 't' instead of '_type' for dictionary names.</jc>
* WriterSerializer <jv>serializer</jv> = JsonSerializer
* .<jsm>create</jsm>()
* .typePropertyName(MyBean.<jk>class</jk>, <js>"t"</js>)
* .dictionary(Foo.<jk>class</jk>, Bar.<jk>class</jk>)
* .build();
*
* <jc>// Produces "{mySimpleField:{t:'foo',...}}".</jc>
* String <jv>json</jv> = <jv>serializer</jv>.serialize(<jk>new</jk> MyBean());
* </p>
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='ja'>{@link Bean#typePropertyName() Bean(typePropertyName)}
* <li class='jm'>{@link BeanContext.Builder#typePropertyName(String)}
* </ul>
*
* @param on The class the type property name applies to.
* @param value
* The new value for this setting.
* <br>The default is <js>"_type"</js>.
* @return This object.
*/
@FluentSetter
public Builder typePropertyName(Class<?> on, String value) {
bcBuilder.typePropertyName(on, value);
return this;
}
/**
* Use enum names.
*
* <p>
* When enabled, enums are always serialized by name, not using {@link Object#toString()}.
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// Create a serializer with debug enabled.</jc>
* WriterSerializer <jv>serializer</jv> = JsonSerializer
* .<jsm>create</jsm>()
* .useEnumNames()
* .build();
*
* <jc>// Enum with overridden toString().</jc>
* <jc>// Will be serialized as ONE/TWO/THREE even though there's a toString() method.</jc>
* <jk>public enum</jk> Option {
* <jsf>ONE</jsf>(1),
* <jsf>TWO</jsf>(2),
* <jsf>THREE</jsf>(3);
*
* <jk>private int</jk> <jf>value</jf>;
*
* Option(<jk>int</jk> <jv>value</jv>) {
* <jk>this</jk>.<jf>value</jf> = <jv>value</jv>;
* }
*
* <ja>@Override</ja>
* <jk>public</jk> String toString() {
* <jk>return</jk> String.<jsm>valueOf</jsm>(<jf>value</jf>);
* }
* }
* </p>
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='jm'>{@link BeanContext.Builder#useEnumNames()}
* </ul>
*
* @return This object.
*/
@FluentSetter
public Builder useEnumNames() {
bcBuilder.useEnumNames();
return this;
}
/**
* Don't use interface proxies.
*
* <p>
* When enabled, interfaces will be instantiated as proxy classes through the use of an
* {@link InvocationHandler} if there is no other way of instantiating them.
* Otherwise, throws a {@link BeanRuntimeException}.
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='ja'>{@link BeanConfig#disableInterfaceProxies()}
* <li class='jm'>{@link BeanContext.Builder#disableInterfaceProxies()}
* </ul>
*
* @return This object.
*/
@FluentSetter
public Builder disableInterfaceProxies() {
bcBuilder.disableInterfaceProxies();
return this;
}
/**
* Use Java Introspector.
*
* <p>
* Using the built-in Java bean introspector will not pick up fields or non-standard getters/setters.
* <br>Most {@link Bean @Bean} annotations will be ignored.
*
* <h5 class='section'>Example:</h5>
* <p class='bjava'>
* <jc>// Create a serializer that only uses the built-in java bean introspector for finding properties.</jc>
* WriterSerializer <jv>serializer</jv> = JsonSerializer
* .<jsm>create</jsm>()
* .useJavaBeanIntrospector()
* .build();
* </p>
*
* <h5 class='section'>See Also:</h5><ul>
* <li class='jmf'>{@link BeanContext.Builder#useJavaBeanIntrospector()}
* </ul>
*
* @return This object.
*/
@FluentSetter
public Builder useJavaBeanIntrospector() {
bcBuilder.useJavaBeanIntrospector();
return this;
}
@Override /* Context.Builder */
public Builder annotations(Annotation...value) {
bcBuilder.annotations(value);
super.annotations(value);
return this;
}
@Override /* Context.Builder */
public Builder debug() {
bcBuilder.debug();
super.debug();
return this;
}
// <FluentSetters>
@Override /* GENERATED - org.apache.juneau.Context.Builder */
public Builder apply(AnnotationWorkList work) {
super.apply(work);
return this;
}
@Override /* GENERATED - org.apache.juneau.Context.Builder */
public Builder applyAnnotations(java.lang.Class<?>...fromClasses) {
super.applyAnnotations(fromClasses);
return this;
}
@Override /* GENERATED - org.apache.juneau.Context.Builder */
public Builder applyAnnotations(Method...fromMethods) {
super.applyAnnotations(fromMethods);
return this;
}
@Override /* GENERATED - org.apache.juneau.Context.Builder */
public Builder cache(Cache<HashKey,? extends org.apache.juneau.Context> value) {
super.cache(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.Context.Builder */
public Builder impl(Context value) {
super.impl(value);
return this;
}
@Override /* GENERATED - org.apache.juneau.Context.Builder */
public Builder type(Class<? extends org.apache.juneau.Context> value) {
super.type(value);
return this;
}
// </FluentSetters>
}
//-----------------------------------------------------------------------------------------------------------------
// Instance
//-----------------------------------------------------------------------------------------------------------------
final BeanContext beanContext;
/**
* Constructor.
*
* @param b The builder for this object.
*/
protected BeanContextable(Builder b) {
super(b);
beanContext = b.bc != null ? b.bc : b.bcBuilder.build();
}
/**
* Returns the bean context for this object.
*
* @return The bean context for this object.
*/
public BeanContext getBeanContext() {
return beanContext;
}
//-----------------------------------------------------------------------------------------------------------------
// Other methods
//-----------------------------------------------------------------------------------------------------------------
@Override /* Context */
protected JsonMap properties() {
return filteredMap("beanContext", beanContext.properties());
}
}