All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.juneau.BeanContext Maven / Gradle / Ivy

// ***************************************************************************************************************************
// * 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.Visibility.*;
import static org.apache.juneau.collections.JsonMap.*;
import static org.apache.juneau.common.internal.StringUtils.*;
import static org.apache.juneau.common.internal.ThrowableUtils.*;
import static org.apache.juneau.internal.ClassUtils.*;
import static org.apache.juneau.internal.CollectionUtils.*;

import java.beans.*;
import java.io.*;
import java.lang.annotation.*;
import java.lang.reflect.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.*;

import org.apache.juneau.annotation.*;
import org.apache.juneau.collections.*;
import org.apache.juneau.cp.*;
import org.apache.juneau.internal.*;
import org.apache.juneau.json.*;
import org.apache.juneau.marshaller.*;
import org.apache.juneau.reflect.*;
import org.apache.juneau.serializer.*;
import org.apache.juneau.swap.*;
import org.apache.juneau.utils.*;

/**
 * Bean context.
 *
 * 

* This class servers multiple purposes: *

    *
  • * Provides the ability to wrap beans inside {@link Map} interfaces. *
  • * Serves as a repository for metadata on POJOs, such as associated {@link Bean @Bean} annotations, * {@link PropertyNamer PropertyNamers}, etc... which are used to tailor how POJOs are serialized and parsed. *
* *

* All serializers and parsers use this context so that they can handle POJOs using a common framework. * *

Bean Contexts
* *

* Bean contexts are created through the {@link BeanContext#create() BeanContext.create()} and {@link Builder#build()} methods. *
These context objects are read-only, reusable, and thread-safe. * *

* Each bean context maintains a cache of {@link ClassMeta} objects that describe information about classes encountered. * These ClassMeta objects are time-consuming to construct. * Therefore, instances of {@link BeanContext} that share the same "BeanContext.*" property values share * the same cache. This allows for efficient reuse of ClassMeta objects so that the information about * classes only needs to be calculated once. * Because of this, many of the properties defined on the {@link BeanContext} class cannot be overridden on the session. * *

Bean Sessions
* *

* Whereas BeanContext objects are permanent, unchangeable, cached, and thread-safe, * {@link BeanSession} objects are ephemeral and not thread-safe. * They are meant to be used as quickly-constructed scratchpads for creating bean maps. * {@link BeanMap} objects can only be created through the session. * *

BeanContext configuration properties
* *

* BeanContexts have several configuration properties that can be used to tweak behavior on how beans are * handled. These are denoted as the static BEAN_* fields on this class. * *

* Some settings (e.g. {@link Builder#beansRequireDefaultConstructor()}) are used to differentiate between bean * and non-bean classes. * Attempting to create a bean map around one of these objects will throw a {@link BeanRuntimeException}. * The purpose for this behavior is so that the serializers can identify these non-bean classes and convert them to * plain strings using the {@link Object#toString()} method. * *

* Some settings (e.g. {@link Builder#beanFieldVisibility(Visibility)}) are used to determine what kinds of properties are * detected on beans. * *

* Some settings (e.g. {@link Builder#beanMapPutReturnsOldValue()}) change the runtime behavior of bean maps. * *

Example:
* *

* // Construct a context from scratch. * BeanContext beanContext = BeanContext * .create() * .beansRequireDefaultConstructor() * .notBeanClasses(Foo.class) * .build(); *

* *
Bean Maps
* *

* {@link BeanMap BeanMaps} are wrappers around Java beans that allow properties to be retrieved and * set using the common {@link Map#put(Object,Object)} and {@link Map#get(Object)} methods. * *

* Bean maps are created in two ways... *

    *
  1. {@link BeanSession#toBeanMap(Object) BeanSession.toBeanMap()} - Wraps an existing bean inside a {@code Map} * wrapper. *
  2. {@link BeanSession#newBeanMap(Class) BeanSession.newBeanMap()} - Create a new bean instance wrapped in a * {@code Map} wrapper. *
* *
Example:
* *

* // A sample bean class * public class Person { * public String getName(); * public void setName(String name); * public int getAge(); * public void setAge(int age); * } * * // Create a new bean session * BeanSession session = BeanContext.DEFAULT.createSession(); * * // Wrap an existing bean in a new bean map * BeanMap<Person> map1 = session.toBeanMap(new Person()); * map1.put("name", "John Smith"); * map1.put("age", 45); * * // Create a new bean instance wrapped in a new bean map * BeanMap<Person> map2 = session.newBeanMap(Person.class); * map2.put("name", "John Smith"); * map2.put("age", 45); * Person person = map2.getBean(); // Get the bean instance that was created. *

* *
Notes:
    *
  • This class is thread safe and reusable. *
* *
See Also:
*/ @SuppressWarnings({"unchecked","rawtypes"}) public class BeanContext extends Context { //----------------------------------------------------------------------------------------------------------------- // Static //----------------------------------------------------------------------------------------------------------------- /* * The default package pattern exclusion list. * Any beans in packages in this list will not be considered beans. */ private static final String[] DEFAULT_NOTBEAN_PACKAGES = { "java.lang", "java.lang.annotation", "java.lang.ref", "java.lang.reflect", "java.io", "java.net", "java.nio.*", "java.util.*" }; /* * The default bean class exclusion list. * Anything in this list will not be considered beans. */ private static final Class[] DEFAULT_NOTBEAN_CLASSES = { Map.class, Collection.class, Reader.class, Writer.class, InputStream.class, OutputStream.class, Throwable.class }; /** Default config. All default settings. */ public static final BeanContext DEFAULT = create().build(); /** Default config. All default settings except sort bean properties. */ public static final BeanContext DEFAULT_SORTED = create().sortProperties().build(); /** Default reusable unmodifiable session. Can be used to avoid overhead of creating a session (for creating BeanMaps for example).*/ public static final BeanSession DEFAULT_SESSION = DEFAULT.createSession().unmodifiable().build(); /** * Creates a new builder for this object. * * @return A new builder. */ public static Builder create() { return new Builder(); } //----------------------------------------------------------------------------------------------------------------- // Builder //----------------------------------------------------------------------------------------------------------------- /** * Builder class. */ @FluentSetters public static class Builder extends Context.Builder { private static final Cache CACHE = Cache.of(HashKey.class, BeanContext.class).build(); Visibility beanClassVisibility, beanConstructorVisibility, beanMethodVisibility, beanFieldVisibility; boolean disableBeansRequireSomeProperties, beanMapPutReturnsOldValue, beansRequireDefaultConstructor, beansRequireSerializable, beansRequireSettersForGetters, disableIgnoreTransientFields, disableIgnoreUnknownNullBeanProperties, disableIgnoreMissingSetters, disableInterfaceProxies, findFluentSetters, ignoreInvocationExceptionsOnGetters, ignoreInvocationExceptionsOnSetters, ignoreUnknownBeanProperties, ignoreUnknownEnumValues, sortProperties, useEnumNames, useJavaBeanIntrospector; String typePropertyName; MediaType mediaType; Locale locale; TimeZone timeZone; Class propertyNamer; List> beanDictionary; List swaps; Set> notBeanClasses; Set notBeanPackages; /** * Constructor. * * All default settings. */ protected Builder() { beanClassVisibility = env("BeanContext.beanClassVisibility", PUBLIC); beanConstructorVisibility = env("BeanContext.beanConstructorVisibility", PUBLIC); beanMethodVisibility = env("BeanContext.beanMethodVisibility", PUBLIC); beanFieldVisibility = env("BeanContext.beanFieldVisibility", PUBLIC); beanDictionary = null; swaps = null; notBeanClasses = null; notBeanPackages = null; disableBeansRequireSomeProperties = env("BeanContext.disableBeansRequireSomeProperties", false); beanMapPutReturnsOldValue = env("BeanContext.beanMapPutReturnsOldValue", false); beansRequireDefaultConstructor = env("BeanContext.beansRequireDefaultConstructor", false); beansRequireSerializable = env("BeanContext.beansRequireSerializable", false); beansRequireSettersForGetters = env("BeanContext.beansRequireSettersForGetters", false); disableIgnoreTransientFields = env("BeanContext.disableIgnoreTransientFields", false); disableIgnoreUnknownNullBeanProperties = env("BeanContext.disableIgnoreUnknownNullBeanProperties", false); disableIgnoreMissingSetters = env("BeanContext.disableIgnoreMissingSetters", false); disableInterfaceProxies = env("BeanContext.disableInterfaceProxies", false); findFluentSetters = env("BeanContext.findFluentSetters", false); ignoreInvocationExceptionsOnGetters = env("BeanContext.ignoreInvocationExceptionsOnGetters", false); ignoreInvocationExceptionsOnSetters = env("BeanContext.ignoreInvocationExceptionsOnSetters", false); ignoreUnknownBeanProperties = env("BeanContext.ignoreUnknownBeanProperties", false); ignoreUnknownEnumValues = env("BeanContext.ignoreUnknownEnumValues", false); sortProperties = env("BeanContext.sortProperties", false); useEnumNames = env("BeanContext.useEnumNames", false); useJavaBeanIntrospector = env("BeanContext.useJavaBeanIntrospector", false); typePropertyName = env("BeanContext.typePropertyName", "_type"); mediaType = env("BeanContext.mediaType", (MediaType)null); timeZone = env("BeanContext.timeZone", (TimeZone)null); locale = env("BeanContext.locale", Locale.getDefault()); propertyNamer = null; } /** * Copy constructor. * * @param copyFrom The bean to copy from. */ protected Builder(BeanContext copyFrom) { super(copyFrom); beanClassVisibility = copyFrom.beanClassVisibility; beanConstructorVisibility = copyFrom.beanConstructorVisibility; beanMethodVisibility = copyFrom.beanMethodVisibility; beanFieldVisibility = copyFrom.beanFieldVisibility; beanDictionary = listFrom(copyFrom.beanDictionary, true); swaps = listFrom(copyFrom.swaps, true); notBeanClasses = classSet(copyFrom.notBeanClasses, true); notBeanPackages = sortedSetFrom(copyFrom.notBeanPackages, true); disableBeansRequireSomeProperties = ! copyFrom.beansRequireSomeProperties; beanMapPutReturnsOldValue = copyFrom.beanMapPutReturnsOldValue; beansRequireDefaultConstructor = copyFrom.beansRequireDefaultConstructor; beansRequireSerializable = copyFrom.beansRequireSerializable; beansRequireSettersForGetters = copyFrom.beansRequireSettersForGetters; disableIgnoreTransientFields = ! copyFrom.ignoreTransientFields; disableIgnoreUnknownNullBeanProperties = ! copyFrom.ignoreUnknownNullBeanProperties; disableIgnoreMissingSetters = ! copyFrom.ignoreMissingSetters; disableInterfaceProxies = ! copyFrom.useInterfaceProxies; findFluentSetters = copyFrom.findFluentSetters; ignoreInvocationExceptionsOnGetters = copyFrom.ignoreInvocationExceptionsOnGetters; ignoreInvocationExceptionsOnSetters = copyFrom.ignoreInvocationExceptionsOnSetters; ignoreUnknownBeanProperties = copyFrom.ignoreUnknownBeanProperties; ignoreUnknownEnumValues = copyFrom.ignoreUnknownEnumValues; sortProperties = copyFrom.sortProperties; useEnumNames = copyFrom.useEnumNames; useJavaBeanIntrospector = copyFrom.useJavaBeanIntrospector; typePropertyName = copyFrom.typePropertyName; mediaType = copyFrom.mediaType; timeZone = copyFrom.timeZone; locale = copyFrom.locale; propertyNamer = copyFrom.propertyNamer; } /** * Copy constructor. * * @param copyFrom The builder to copy from. */ protected Builder(Builder copyFrom) { super(copyFrom); beanClassVisibility = copyFrom.beanClassVisibility; beanConstructorVisibility = copyFrom.beanConstructorVisibility; beanMethodVisibility = copyFrom.beanMethodVisibility; beanFieldVisibility = copyFrom.beanFieldVisibility; beanDictionary = copyOf(copyFrom.beanDictionary); swaps = copyOf(copyFrom.swaps); notBeanClasses = classSet(copyFrom.notBeanClasses); notBeanPackages = sortedSetFrom(copyFrom.notBeanPackages); disableBeansRequireSomeProperties = copyFrom.disableBeansRequireSomeProperties; beanMapPutReturnsOldValue = copyFrom.beanMapPutReturnsOldValue; beansRequireDefaultConstructor = copyFrom.beansRequireDefaultConstructor; beansRequireSerializable = copyFrom.beansRequireSerializable; beansRequireSettersForGetters = copyFrom.beansRequireSettersForGetters; disableIgnoreTransientFields = copyFrom.disableIgnoreTransientFields; disableIgnoreUnknownNullBeanProperties = copyFrom.disableIgnoreUnknownNullBeanProperties; disableIgnoreMissingSetters = copyFrom.disableIgnoreMissingSetters; disableInterfaceProxies = copyFrom.disableInterfaceProxies; findFluentSetters = copyFrom.findFluentSetters; ignoreInvocationExceptionsOnGetters = copyFrom.ignoreInvocationExceptionsOnGetters; ignoreInvocationExceptionsOnSetters = copyFrom.ignoreInvocationExceptionsOnSetters; ignoreUnknownBeanProperties = copyFrom.ignoreUnknownBeanProperties; ignoreUnknownEnumValues = copyFrom.ignoreUnknownEnumValues; sortProperties = copyFrom.sortProperties; useEnumNames = copyFrom.useEnumNames; useJavaBeanIntrospector = copyFrom.useJavaBeanIntrospector; typePropertyName = copyFrom.typePropertyName; mediaType = copyFrom.mediaType; timeZone = copyFrom.timeZone; locale = copyFrom.locale; propertyNamer = copyFrom.propertyNamer; } @Override /* Context.Builder */ public Builder copy() { return new Builder(this); } @Override /* Context.Builder */ public BeanContext build() { return cache(CACHE).build(BeanContext.class); } @Override /* Context.Builder */ public HashKey hashKey() { return HashKey.of( super.hashKey(), beanClassVisibility, beanConstructorVisibility, beanMethodVisibility, beanFieldVisibility, beanDictionary, swaps, notBeanClasses, notBeanPackages, integer( disableBeansRequireSomeProperties, beanMapPutReturnsOldValue, beansRequireDefaultConstructor, beansRequireSerializable, beansRequireSettersForGetters, disableIgnoreTransientFields, disableIgnoreUnknownNullBeanProperties, disableIgnoreMissingSetters, disableInterfaceProxies, findFluentSetters, ignoreInvocationExceptionsOnGetters, ignoreInvocationExceptionsOnSetters, ignoreUnknownBeanProperties, ignoreUnknownEnumValues, sortProperties, useEnumNames, useJavaBeanIntrospector ), typePropertyName, mediaType, timeZone, locale, propertyNamer ); } private int integer(boolean...values) { int n = 0; for (boolean b : values) n = (n << 1) | (b ? 1 : 0); return n; } //----------------------------------------------------------------------------------------------------------------- // Properties //----------------------------------------------------------------------------------------------------------------- /** * Minimum bean class visibility. * *

* Classes are not considered beans unless they meet the minimum visibility requirements. * For example, if the visibility is PUBLIC and the bean class is protected, 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. * *

Example:
*

* // A bean with a protected class and one field. * protected class MyBean { * public String foo = "bar"; * } * * // Create a serializer that's capable of serializing the class. * WriterSerializer serializer = JsonSerializer * .create() * .beanClassVisibility(PROTECTED) * .build(); * * // Produces: {"foo","bar"} * String json = serializer.serialize(new MyBean()); *

* *
Notes:
    *
  • The {@link Bean @Bean} annotation can be used on a non-public bean class to override this setting. *
  • The {@link BeanIgnore @BeanIgnore} annotation can also be used on a public bean class to ignore it as a bean. *
* *
See Also:
    *
  • {@link org.apache.juneau.annotation.BeanConfig#beanClassVisibility()} *
* * @param value * The new value for this setting. *
The default is {@link Visibility#PUBLIC}. * @return This object. */ @FluentSetter public Builder beanClassVisibility(Visibility value) { beanClassVisibility = value; return this; } /** * Minimum bean constructor visibility. * *

* Only look for constructors with the specified minimum visibility. * *

* This setting affects the logic for finding no-arg constructors for bean. Normally, only public no-arg * constructors are used. Use this setting if you want to reduce the visibility requirement. * *

Example:
*

* // A bean with a protected constructor and one field. * public class MyBean { * public String foo; * * protected MyBean() {} * } * * // Create a parser capable of calling the protected constructor. * ReaderParser parser = ReaderParser * .create() * .beanConstructorVisibility(PROTECTED) * .build(); * * // Use it. * MyBean myBean = parser.parse("{foo:'bar'}", MyBean.class); *

* *
Notes:
    *
  • The {@link Beanc @Beanc} annotation can also be used to expose a non-public constructor. *
  • The {@link BeanIgnore @BeanIgnore} annotation can also be used on a public bean constructor to ignore it. *
* *
See Also:
    *
  • {@link org.apache.juneau.annotation.BeanConfig#beanConstructorVisibility()} *
* * @param value * The new value for this setting. *
The default is {@link Visibility#PUBLIC}. * @return This object. */ @FluentSetter public Builder beanConstructorVisibility(Visibility value) { beanConstructorVisibility = value; return this; } /** * Minimum bean field visibility. * *

* Only look for bean fields with the specified minimum visibility. * *

* This affects which fields on a bean class are considered bean properties. Normally only public fields are considered. * Use this setting if you want to reduce the visibility requirement. * *

Example:
*

* // A bean with a protected field. * public class MyBean { * protected String foo = "bar"; * } * * // Create a serializer that recognizes the protected field. * WriterSerializer serializer = JsonSerializer * .create() * .beanFieldVisibility(PROTECTED) * .build(); * * // Produces: {"foo":"bar"} * String json = serializer.serialize(new MyBean()); *

* *

* Bean fields can be ignored as properties entirely by setting the value to {@link Visibility#NONE} * *

* // Disable using fields as properties entirely. * WriterSerializer serializer = JsonSerializer * .create() * .beanFieldVisibility(NONE) * .build(); *

* *
Notes:
    *
  • The {@link Beanp @Beanp} annotation can also be used to expose a non-public field. *
  • The {@link BeanIgnore @BeanIgnore} annotation can also be used on a public bean field to ignore it as a bean property. *
* *
See Also:
    *
  • {@link org.apache.juneau.annotation.BeanConfig#beanFieldVisibility()} *
* * @param value * The new value for this setting. *
The default is {@link Visibility#PUBLIC}. * @return This object. */ @FluentSetter public Builder beanFieldVisibility(Visibility value) { beanFieldVisibility = value; return this; } /** * Bean interceptor. * *

* Bean interceptors can be used to intercept calls to getters and setters and alter their values in transit. * *

Example:
*

* // Interceptor that strips out sensitive information. * public class AddressInterceptor extends BeanInterceptor<Address> { * * public Object readProperty(Address bean, String name, Object value) { * if ("taxInfo".equals(name)) * return "redacted"; * return value; * } * * public Object writeProperty(Address bean, String name, Object value) { * if ("taxInfo".equals(name) && "redacted".equals(value)) * return TaxInfoUtils.lookup(bean.getStreet(), bean.getCity(), bean.getState()); * return value; * } * } * * // Our bean class. * public class Address { * public String getTaxInfo() {...} * public void setTaxInfo(String value) {...} * } * * // Register filter on serializer or parser. * WriterSerializer serializer = JsonSerializer * .create() * .beanInterceptor(Address.class, AddressInterceptor.class) * .build(); * * // Produces: {"taxInfo":"redacted"} * String json = serializer.serialize(new Address()); *

* *
See Also:
    *
  • {@link BeanInterceptor} *
  • {@link Bean#interceptor() Bean(interceptor)} *
* * @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> value) { return annotations(BeanAnnotation.create(on).interceptor(value).build()); } /** * BeanMap.put() returns old property value. * *

* When enabled, then the {@link BeanMap#put(String,Object) BeanMap.put()} method will return old property * values. Otherwise, it returns null. * *

* Disabled by default because it introduces a slight performance penalty during serialization. * *

Example:
*

* // Create a context that creates BeanMaps with normal put() behavior. * BeanContext context = BeanContext * .create() * .beanMapPutReturnsOldValue() * .build(); * * BeanMap<MyBean> myBeanMap = context.createSession().toBeanMap(new MyBean()); * myBeanMap.put("foo", "bar"); * Object oldValue = myBeanMap.put("foo", "baz"); // oldValue == "bar" *

* *
See Also:
    *
  • {@link org.apache.juneau.annotation.BeanConfig#beanMapPutReturnsOldValue()} *
* * @return This object. */ @FluentSetter public Builder beanMapPutReturnsOldValue() { return beanMapPutReturnsOldValue(true); } /** * Same as {@link #beanMapPutReturnsOldValue()} but allows you to explicitly specify the value. * * @param value The value for this setting. * @return This object. */ @FluentSetter public Builder beanMapPutReturnsOldValue(boolean value) { beanMapPutReturnsOldValue = value; return this; } /** * Minimum bean method visibility. * *

* Only look for bean methods with the specified minimum visibility. * *

* This affects which methods are detected as getters and setters on a bean class. Normally only public getters and setters are considered. * Use this setting if you want to reduce the visibility requirement. * *

Example:
*

* // A bean with a protected getter. * public class MyBean { * public String getFoo() { return "foo"; } * protected String getBar() { return "bar"; } * } * * // Create a serializer that looks for protected getters and setters. * WriterSerializer serializer = JsonSerializer * .create() * .beanMethodVisibility(PROTECTED) * .build(); * * // Produces: {"foo":"foo","bar":"bar"} * String json = serializer.serialize(new MyBean()); *

* *
Notes:
    *
  • The {@link Beanp @Beanp} annotation can also be used to expose a non-public method. *
  • The {@link BeanIgnore @BeanIgnore} annotation can also be used on a public bean getter/setter to ignore it as a bean property. *
* *
See Also:
    *
  • {@link org.apache.juneau.annotation.BeanConfig#beanMethodVisibility()} *
* * @param value * The new value for this setting. *
The default is {@link Visibility#PUBLIC} * @return This object. */ @FluentSetter public Builder beanMethodVisibility(Visibility value) { beanMethodVisibility = value; return this; } /** * Beans require no-arg constructors. * *

* 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. * *

Example:
*

* // A bean without a no-arg constructor. * public class MyBean { * * // A property method. * public String foo = "bar"; * * // A no-arg constructor * public MyBean(String foo) { * this.foo = foo; * } * * @Override * public String toString() { * return "bar"; * } * } * * // Create a serializer that ignores beans without default constructors. * WriterSerializer serializer = JsonSerializer * .create() * .beansRequireDefaultConstructor() * .build(); * * // Produces: "bar" * String json = serializer.serialize(new MyBean()); *

* *
Notes:
    *
  • The {@link Bean @Bean} annotation can be used on a bean class to override this setting. *
  • The {@link BeanIgnore @BeanIgnore} annotation can also be used on a class to ignore it as a bean. *
* *
See Also:
    *
  • {@link org.apache.juneau.annotation.BeanConfig#beansRequireDefaultConstructor()} *
* * @return This object. */ @FluentSetter public Builder beansRequireDefaultConstructor() { return beansRequireDefaultConstructor(true); } /** * Same as {@link #beansRequireDefaultConstructor()} but allows you to explicitly specify the value. * * @param value The value for this setting. * @return This object. */ @FluentSetter public Builder beansRequireDefaultConstructor(boolean value) { beansRequireDefaultConstructor = value; return this; } /** * Beans require Serializable interface. * *

* 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. * *

Example:
*

* // A bean without a Serializable interface. * public class MyBean { * * // A property method. * public String foo = "bar"; * * @Override * public String toString() { * return "bar"; * } * } * * // Create a serializer that ignores beans not implementing Serializable. * WriterSerializer serializer = JsonSerializer * .create() * .beansRequireSerializable() * .build(); * * // Produces: "bar" * String json = serializer.serialize(new MyBean()); *

* *
Notes:
    *
  • The {@link Bean @Bean} annotation can be used on a bean class to override this setting. *
  • The {@link BeanIgnore @BeanIgnore} annotation can also be used on a class to ignore it as a bean. *
* *
See Also:
    *
  • {@link org.apache.juneau.annotation.BeanConfig#beansRequireSerializable()} *
* * @return This object. */ @FluentSetter public Builder beansRequireSerializable() { return beansRequireSerializable(true); } /** * Same as {@link #beansRequireSerializable()} but allows you to explicitly specify the value. * * @param value The value for this setting. * @return This object. */ @FluentSetter public Builder beansRequireSerializable(boolean value) { beansRequireSerializable = value; return this; } /** * Beans require setters for getters. * *

* When enabled, ignore read-only properties (properties with getters but not setters). * *

Example:
*

* // A bean without a Serializable interface. * public class MyBean { * * // A read/write property. * public String getFoo() { return "foo"; } * public void setFoo(String foo) { ... } * * // A read-only property. * public String getBar() { return "bar"; } * } * * // Create a serializer that ignores bean properties without setters. * WriterSerializer serializer = JsonSerializer * .create() * .beansRequireSettersForGetters() * .build(); * * // Produces: {"foo":"foo"} * String json = serializer.serialize(new MyBean()); *

* *
Notes:
    *
  • The {@link Beanp @Beanp} annotation can be used on the getter to override this setting. *
  • The {@link BeanIgnore @BeanIgnore} annotation can also be used on getters to ignore them as bean properties. *
* * @return This object. */ @FluentSetter public Builder beansRequireSettersForGetters() { return beansRequireSettersForGetters(true); } /** * Same as {@link #beansRequireSettersForGetters()} but allows you to explicitly specify the value. * * @param value The value for this setting. * @return This object. */ @FluentSetter public Builder beansRequireSettersForGetters(boolean value) { beansRequireSettersForGetters = value; return this; } /** * Beans don't require at least one property. * *

* 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. * *

* The {@link Bean @Bean} annotation can be used on a class to override this setting when true. * *

Example:
*

* // A bean with no properties. * public class MyBean { * } * * // Create a serializer that serializes beans even if they have zero properties. * WriterSerializer serializer = JsonSerializer * .create() * .disableBeansRequireSomeProperties() * .build(); * * // Produces: {} * String json = serializer.serialize(new MyBean()); *

* *
Notes:
    *
  • 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. *
* *
See Also:
    *
  • {@link org.apache.juneau.annotation.BeanConfig#disableBeansRequireSomeProperties()} *
* * @return This object. */ @FluentSetter public Builder disableBeansRequireSomeProperties() { return disableBeansRequireSomeProperties(true); } /** * Same as {@link #disableBeansRequireSomeProperties()} but allows you to explicitly specify the value. * * @param value The value for this setting. * @return This object. */ @FluentSetter public Builder disableBeansRequireSomeProperties(boolean value) { disableBeansRequireSomeProperties = value; return this; } /** * Bean property includes. * *

* Specifies the set and order of names of properties associated with the bean class. * *

* For example, beanProperties(MyBean.class, "foo,bar") means only serialize the foo and * bar 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. * *

* 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. * *

* Setting applies to specified class and all subclasses. * *

Example:
*

* // A bean with 3 properties. * public class MyBean { * public String * foo = "foo", * bar = "bar", * baz = "baz"; * } * * // Create a serializer that includes only the 'foo' and 'bar' properties on the MyBean class. * WriterSerializer serializer = JsonSerializer * .create() * .beanProperties(MyBean.class, "foo,bar") * .build(); * * // Produces: {"foo":"foo","bar":"bar"} * String json = serializer.serialize(new MyBean()); *

* *

* This method is functionally equivalent to the following code: *

* builder.annotations(BeanAnnotation.create(beanClass).properties(properties).build()); *

* *
See Also:
    *
  • {@link Bean#properties()}/{@link Bean#p()} - On an annotation on the bean class itself. *
* * @param beanClass The bean class. * @param properties Comma-delimited list of property names. * @return This object. */ @FluentSetter public Builder beanProperties(Class beanClass, String properties) { return annotations(BeanAnnotation.create(beanClass).p(properties).build()); } /** * Bean property includes. * *

* Specifies the set and order of names of properties associated with bean classes. * *

* For example, beanProperties(AMap.of("MyBean", "foo,bar")) means only serialize the foo and * bar 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. * *

* 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. * *

* Setting applies to specified class and all subclasses. * *

Example:
*

* // A bean with 3 properties. * public class MyBean { * public String * foo = "foo", * bar = "bar", * baz = "baz"; * } * * // Create a serializer that includes only the 'foo' and 'bar' properties on the MyBean class. * WriterSerializer serializer = JsonSerializer * .create() * .beanProperties(AMap.of("MyBean", "foo,bar")) * .build(); * * // Produces: {"foo":"foo","bar":"bar"} * String json = serializer.serialize(new MyBean()); *

* *

* This method is functionally equivalent to the following code for each entry: *

* builder.annotations(BeanAnnotation.create(key).properties(value.toString()).build()); *

* *
See Also:
    *
  • {@link Bean#properties()} / {@link Bean#p()}- On an annotation on the bean class itself. *
* * @param values * The values to add to this builder. *
Keys are bean class names which can be a simple name, fully-qualified name, or "*" for all beans. *
Values are comma-delimited lists of property names. Non-String objects are first converted to Strings. * @return This object. */ @FluentSetter public Builder beanProperties(Map values) { values.forEach((k,v) -> annotations(BeanAnnotation.create(k).p(stringify(v)).build())); return this; } /** * Bean property includes. * *

* Specifies the set and order of names of properties associated with the bean class. * *

* For example, beanProperties("MyBean", "foo,bar") means only serialize the foo and * bar 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. * *

* 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. * *

* Setting applies to specified class and all subclasses. * *

Example:
*

* // A bean with 3 properties. * public class MyBean { * public String * foo = "foo", * bar = "bar", * baz = "baz"; * } * * // Create a serializer that includes only the 'foo' and 'bar' properties on the MyBean class. * WriterSerializer serializer = JsonSerializer * .create() * .beanProperties("MyBean", "foo,bar") * .build(); * * // Produces: {"foo":"foo","bar":"bar"} * String json = serializer.serialize(new MyBean()); *

* *

* This method is functionally equivalent to the following code: *

* builder.annotations(BeanAnnotation.create(beanClassName).properties(properties).build()); *

* *
See Also:
    *
  • {@link Bean#properties()} / {@link Bean#p()} - On an annotation on the bean class itself. *
* * @param beanClassName * The bean class name. *
Can be a simple name, fully-qualified name, or "*" for all beans. * @param properties Comma-delimited list of property names. * @return This object. */ @FluentSetter public Builder beanProperties(String beanClassName, String properties) { return annotations(BeanAnnotation.create(beanClassName).p(properties).build()); } /** * Bean property excludes. * *

* Specifies to exclude the specified list of properties for the specified bean class. * *

* Same as {@link #beanProperties(Class, String)} except you specify a list of bean property names that you want to exclude from * serialization. * *

* Setting applies to specified class and all subclasses. * *

Example:
*

* // A bean with 3 properties. * public class MyBean { * public String * foo = "foo", * bar = "bar", * baz = "baz"; * } * * // Create a serializer that excludes the "bar" and "baz" properties on the MyBean class. * WriterSerializer serializer = JsonSerializer * .create() * .beanPropertiesExcludes(MyBean.class, "bar,baz") * .build(); * * // Produces: {"foo":"foo"} * String json = serializer.serialize(new MyBean()); *

* *

* This method is functionally equivalent to the following code: *

* builder.annotations(BeanAnnotation.create(beanClass).excludeProperties(properties).build()); *

* *
See Also:
    *
  • {@link Bean#excludeProperties()} / {@link Bean#xp()} *
* * @param beanClass The bean class. * @param properties Comma-delimited list of property names. * @return This object. */ @FluentSetter public Builder beanPropertiesExcludes(Class beanClass, String properties) { return annotations(BeanAnnotation.create(beanClass).xp(properties).build()); } /** * Bean property excludes. * *

* Specifies to exclude the specified list of properties for the specified bean classes. * *

* Same as {@link #beanProperties(Map)} except you specify a list of bean property names that you want to exclude from * serialization. * *

* Setting applies to specified class and all subclasses. * *

Example:
*

* // A bean with 3 properties. * public class MyBean { * public String * foo = "foo", * bar = "bar", * baz = "baz"; * } * * // Create a serializer that excludes the "bar" and "baz" properties on the MyBean class. * WriterSerializer serializer = JsonSerializer * .create() * .beanPropertiesExcludes(AMap.of("MyBean", "bar,baz")) * .build(); * * // Produces: {"foo":"foo"} * String json = serializer.serialize(new MyBean()); *

* *

* This method is functionally equivalent to the following code for each entry: *

* builder.annotations(BeanAnnotation.create(key).excludeProperties(value.toString()).build()); *

* *
See Also:
    *
  • {@link Bean#excludeProperties()} / {@link Bean#xp()} *
* * @param values * The values to add to this builder. *
Keys are bean class names which can be a simple name, fully-qualified name, or "*" for all beans. *
Values are comma-delimited lists of property names. Non-String objects are first converted to Strings. * @return This object. */ @FluentSetter public Builder beanPropertiesExcludes(Map values) { values.forEach((k,v) -> annotations(BeanAnnotation.create(k).xp(stringify(v)).build())); return this; } /** * Bean property excludes. * *

* Specifies to exclude the specified list of properties for the specified bean class. * *

* Same as {@link #beanPropertiesExcludes(String, String)} except you specify a list of bean property names that you want to exclude from * serialization. * *

* Setting applies to specified class and all subclasses. * *

Example:
*

* // A bean with 3 properties. * public class MyBean { * public String * foo = "foo", * bar = "bar", * baz = "baz"; * } * * // Create a serializer that excludes the "bar" and "baz" properties on the MyBean class. * WriterSerializer serializer = JsonSerializer * .create() * .beanPropertiesExcludes("MyBean", "bar,baz") * .build(); * * // Produces: {"foo":"foo"} * String json = serializer.serialize(new MyBean()); *

* *

* This method is functionally equivalent to the following code: *

* builder.annotations(BeanAnnotation.create(beanClassName).excludeProperties(properties).build()); *

* *
See Also:
    *
  • {@link Bean#excludeProperties()} / {@link Bean#xp()} *
* * @param beanClassName * The bean class name. *
Can be a simple name, fully-qualified name, or "*" for all bean classes. * @param properties Comma-delimited list of property names. * @return This object. */ @FluentSetter public Builder beanPropertiesExcludes(String beanClassName, String properties) { return annotations(BeanAnnotation.create(beanClassName).xp(properties).build()); } /** * Read-only bean properties. * *

* 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. * *

Example:
*

* // A bean with 3 properties. * public class MyBean { * public String foo, bar, baz; * } * * // Create a serializer with read-only property settings. * WriterSerializer serializer = JsonSerializer * .create() * .beanPropertiesReadOnly(MyBean.class, "bar,baz") * .build(); * * // All 3 properties will be serialized. * String json = serializer.serialize(new MyBean()); * * // Create a parser with read-only property settings. * ReaderParser parser = JsonParser * .create() * .beanPropertiesReadOnly(MyBean.class, "bar,baz") * .ignoreUnknownBeanProperties() * .build(); * * // Parser ignores bar and baz properties. * MyBean myBean = parser.parse("{foo:'foo',bar:'bar',baz:'baz'}", MyBean.class); *

* *

* This method is functionally equivalent to the following code: *

* builder.annotations(BeanAnnotation.create(beanClass).readOnlyProperties(properties).build()); *

* *
See Also:
    *
  • {@link Bean#readOnlyProperties()} / {@link Bean#ro()} *
* * @param beanClass The bean class. * @param properties Comma-delimited list of property names. * @return This object. */ @FluentSetter public Builder beanPropertiesReadOnly(Class beanClass, String properties) { return annotations(BeanAnnotation.create(beanClass).ro(properties).build()); } /** * Read-only bean properties. * *

* 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. * *

Example:
*

* // A bean with 3 properties. * public class MyBean { * public String foo, bar, baz; * } * * // Create a serializer with read-only property settings. * WriterSerializer serializer = JsonSerializer * .create() * .beanPropertiesReadOnly(AMap.of("MyBean", "bar,baz")) * .build(); * * // All 3 properties will be serialized. * String json = serializer.serialize(new MyBean()); * * // Create a parser with read-only property settings. * ReaderParser parser = JsonParser * .create() * .beanPropertiesReadOnly(AMap.of("MyBean", "bar,baz")) * .ignoreUnknownBeanProperties() * .build(); * * // Parser ignores bar and baz properties. * MyBean myBean = parser.parse("{foo:'foo',bar:'bar',baz:'baz'}", MyBean.class); *

* *

* This method is functionally equivalent to the following code for each entry: *

* builder.annotations(BeanAnnotation.create(key).readOnlyProperties(value.toString()).build()); *

* *
See Also:
    *
  • {@link Bean#readOnlyProperties()} / {@link Bean#ro()} *
* * @param values * The values to add to this builder. *
Keys are bean class names which can be a simple name, fully-qualified name, or "*" for all beans. *
Values are comma-delimited lists of property names. Non-String objects are first converted to Strings. * @return This object. */ @FluentSetter public Builder beanPropertiesReadOnly(Map values) { values.forEach((k,v) -> annotations(BeanAnnotation.create(k).ro(stringify(v)).build())); return this; } /** * Read-only bean properties. * *

* 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. * *

Example:
*

* // A bean with 3 properties. * public class MyBean { * public String foo, bar, baz; * } * * // Create a serializer with read-only property settings. * WriterSerializer serializer = JsonSerializer * .create() * .beanPropertiesReadOnly("MyBean", "bar,baz") * .build(); * * // All 3 properties will be serialized. * String json = serializer.serialize(new MyBean()); * * // Create a parser with read-only property settings. * ReaderParser parser = JsonParser * .create() * .beanPropertiesReadOnly("MyBean", "bar,baz") * .ignoreUnknownBeanProperties() * .build(); * * // Parser ignores bar and baz properties. * MyBean myBean = parser.parse("{foo:'foo',bar:'bar',baz:'baz'}", MyBean.class); *

* *

* This method is functionally equivalent to the following code: *

* builder.annotations(BeanAnnotation.create(beanClassName).readOnlyProperties(properties).build()); *

* *
See Also:
    *
  • {@link Bean#readOnlyProperties()} / {@link Bean#ro()} *
* * @param beanClassName * The bean class name. *
Can be a simple name, fully-qualified name, or "*" for all bean classes. * @param properties Comma-delimited list of property names. * @return This object. */ @FluentSetter public Builder beanPropertiesReadOnly(String beanClassName, String properties) { return annotations(BeanAnnotation.create(beanClassName).ro(properties).build()); } /** * Write-only bean properties. * *

* 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. * *

Example:
*

* // A bean with 3 properties. * public class MyBean { * public String foo, bar, baz; * } * * // Create a serializer with write-only property settings. * WriterSerializer serializer = JsonSerializer * .create() * .beanPropertiesWriteOnly(MyBean.class, "bar,baz") * .build(); * * // Only foo will be serialized. * String json = serializer.serialize(new MyBean()); * * // Create a parser with write-only property settings. * ReaderParser parser = JsonParser * .create() * .beanPropertiesWriteOnly(MyBean.class, "bar,baz") * .build(); * * // Parser parses all 3 properties. * MyBean myBean = parser.parse("{foo:'foo',bar:'bar',baz:'baz'}", MyBean.class); *

* *

* This method is functionally equivalent to the following code: *

* builder.annotations(BeanAnnotation.create(beanClass).writeOnlyProperties(properties).build()); *

* *
See Also:
    *
  • {@link Bean#writeOnlyProperties()} / {@link Bean#wo()} *
* * @param beanClass The bean class. * @param properties Comma-delimited list of property names. * @return This object. */ @FluentSetter public Builder beanPropertiesWriteOnly(Class beanClass, String properties) { return annotations(BeanAnnotation.create(beanClass).wo(properties).build()); } /** * Write-only bean properties. * *

* 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. * *

Example:
*

* // A bean with 3 properties. * public class MyBean { * public String foo, bar, baz; * } * * // Create a serializer with write-only property settings. * WriterSerializer serializer = JsonSerializer * .create() * .beanPropertiesWriteOnly(AMap.of("MyBean", "bar,baz")) * .build(); * * // Only foo will be serialized. * String json = serializer.serialize(new MyBean()); * * // Create a parser with write-only property settings. * ReaderParser parser = JsonParser * .create() * .beanPropertiesWriteOnly(AMap.of("MyBean", "bar,baz")) * .build(); * * // Parser parses all 3 properties. * MyBean myBean = parser.parse("{foo:'foo',bar:'bar',baz:'baz'}", MyBean.class); *

* *

* This method is functionally equivalent to the following code for each entry: *

* builder.annotations(BeanAnnotation.create(key).writeOnlyProperties(value.toString()).build()); *

* *
See Also:
    *
  • {@link Bean#writeOnlyProperties()} / {@link Bean#wo()} *
* * @param values * The values to add to this builder. *
Keys are bean class names which can be a simple name, fully-qualified name, or "*" for all beans. *
Values are comma-delimited lists of property names. Non-String objects are first converted to Strings. * @return This object. */ @FluentSetter public Builder beanPropertiesWriteOnly(Map values) { values.forEach((k,v) -> annotations(BeanAnnotation.create(k).wo(stringify(v)).build())); return this; } /** * Write-only bean properties. * *

* 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. * *

Example:
*

* // A bean with 3 properties. * public class MyBean { * public String foo, bar, baz; * } * * // Create a serializer with write-only property settings. * WriterSerializer serializer = JsonSerializer * .create() * .beanPropertiesWriteOnly("MyBean", "bar,baz") * .build(); * * // Only foo will be serialized. * String json = serializer.serialize(new MyBean()); * * // Create a parser with write-only property settings. * ReaderParser parser = JsonParser * .create() * .beanPropertiesWriteOnly("MyBean", "bar,baz") * .build(); * * // Parser parses all 3 properties. * MyBean myBean = parser.parse("{foo:'foo',bar:'bar',baz:'baz'}", MyBean.class); *

* *

* This method is functionally equivalent to the following code: *

* builder.annotations(BeanAnnotation.create(beanClassName).writeOnlyProperties(properties).build()); *

* *
See Also:
    *
  • {@link Bean#writeOnlyProperties()} / {@link Bean#wo()} *
* * @param beanClassName * The bean class name. *
Can be a simple name, fully-qualified name, or "*" for all bean classes. * @param properties Comma-delimited list of property names. * @return This object. */ @FluentSetter public Builder beanPropertiesWriteOnly(String beanClassName, String properties) { return annotations(BeanAnnotation.create(beanClassName).wo(properties).build()); } /** * Bean dictionary. * *

* The list of classes that make up the bean dictionary in this bean context. * *

* Values are prepended to the list so that later calls can override classes of earlier calls. * *

* 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 Foo has a type-name of "myfoo", then it would end up * serialized as "{_type:'myfoo',...}" in JSON * or "<myfoo>...</myfoo>" in XML. * *

* This setting tells the parsers which classes to look for when resolving "_type" attributes. * *

* Values can consist of any of the following types: *

    *
  • Any bean class that specifies a value for {@link Bean#typeName() @Bean(typeName)}. *
  • Any subclass of {@link BeanDictionaryList} containing a collection of bean classes with type name annotations. *
  • Any subclass of {@link BeanDictionaryMap} containing a mapping of type names to classes without type name annotations. *
  • Any array or collection of the objects above. *
* *
Example:
*

* // POJOs with @Bean(name) annotations. * @Bean(typeName="foo") * public class Foo {...} * @Bean(typeName="bar") * public class Bar {...} * * // Create a parser and tell it which classes to try to resolve. * ReaderParser parser = JsonParser * .create() * .dictionary(Foo.class, Bar.class) * .addBeanTypes() * .build(); * * // A bean with a field with an indeterminate type. * public class MyBean { * public Object mySimpleField; * } * * // Parse bean. * MyBean myBean = parser.parse("{mySimpleField:{_type:'foo',...}}", MyBean.class); *

* *

* Another option is to use the {@link Bean#dictionary()} annotation on the POJO class itself: * *

* // Instead of by parser, define a bean dictionary on a class through an annotation. * // This applies to all properties on this class and all subclasses. * @Bean(dictionary={Foo.class,Bar.class}) * public class MyBean { * public Object mySimpleField; // May contain Foo or Bar object. * public Map<String,Object> myMapField; // May contain Foo or Bar objects. * } *

* *

* A typical usage is to allow for HTML documents to be parsed back into HTML beans: *

* // Use the predefined HTML5 bean dictionary which is a BeanDictionaryList. * ReaderParser parser = HtmlParser * .create() * .dictionary(HtmlBeanDictionary.class) * .build(); * * // Parse an HTML body into HTML beans. * Body body = parser.parse("<body><ul><li>foo</li><li>bar</li></ul>", Body.class); *

* *
See Also:
    *
  • {@link org.apache.juneau.annotation.Bean#dictionary()} *
  • {@link org.apache.juneau.annotation.Beanp#dictionary()} *
  • {@link org.apache.juneau.annotation.BeanConfig#dictionary()} *
  • {@link org.apache.juneau.annotation.BeanConfig#dictionary_replace()} *
  • {@link org.apache.juneau.BeanContext.Builder#beanDictionary(Class...)} *
* * @param values * The values to add to this setting. * @return This object. */ @FluentSetter public Builder beanDictionary(Class...values) { return beanDictionary(alist(values)); } /** * Same as {@link #beanDictionary(Class...)} but allows you to pass in a collection of classes. * * @param values * The values to add to this setting. * @return This object. * @see #beanDictionary(Class...) */ @FluentSetter public Builder beanDictionary(Collection> values) { beanDictionary().addAll(0, values); return this; } /** * Returns the bean dictionary list. * *

* Gives access to the inner list if you need to make more than simple additions via {@link #beanDictionary(Class...)}. * * @return The bean dictionary list. * @see #beanDictionary(Class...) */ public List> beanDictionary() { if (beanDictionary == null) beanDictionary = list(); return beanDictionary; } /** * Bean dictionary. * *

* This is identical to {@link #beanDictionary(Class...)}, but specifies a dictionary within the context of * a single class as opposed to globally. * *

Example:
*

* // POJOs with @Bean(name) annotations. * @Bean(typeName="foo") * public class Foo {...} * @Bean(typeName="bar") * public class Bar {...} * * // A bean with a field with an indeterminate type. * public class MyBean { * public Object mySimpleField; * } * * // Create a parser and tell it which classes to try to resolve. * ReaderParser parser = JsonParser * .create() * .dictionaryOn(MyBean.class, Foo.class, Bar.class) * .build(); * * // Parse bean. * MyBean myBean = parser.parse("{mySimpleField:{_type:'foo',...}}", MyBean.class); *

* *

* This is functionally equivalent to the {@link Bean#dictionary()} annotation. * *

See Also:
    *
  • {@link Bean#dictionary()} *
  • {@link #beanDictionary(Class...)} *
* * @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) { return annotations(BeanAnnotation.create(on).dictionary(values).build()); } /** * POJO example. * *

* Specifies an example of the specified class. * *

* Examples are used in cases such as POJO examples in Swagger documents. * *

Example:
*

* // Create a serializer that excludes the 'foo' and 'bar' properties on the MyBean class. * WriterSerializer serializer = JsonSerializer * .create() * .example(MyBean.class, new MyBean().setFoo("foo").setBar(123)) * .build(); *

* *

* This is a shorthand method for the following code: *

* builder.annotations(MarshalledAnnotation.create(pojoClass).example(Json5.DEFAULT.toString(object)).build()) *

* *
Notes:
    *
  • 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. *
* *

* POJO examples can also be defined on classes via the following: *

    *
  • The {@link Marshalled#example()} annotation on the class itself. *
  • A static field annotated with {@link Example @Example}. *
  • A static method annotated with {@link Example @Example} with zero arguments or one {@link BeanSession} argument. *
  • A static method with name example with no arguments or one {@link BeanSession} argument. *
* * @param The POJO class. * @param pojoClass The POJO class. * @param o * An instance of the POJO class used for examples. * @return This object. */ @FluentSetter public Builder example(Class pojoClass, T o) { return annotations(MarshalledAnnotation.create(pojoClass).example(Json5.of(o)).build()); } /** * POJO example. * *

* Specifies an example in JSON of the specified class. * *

* Examples are used in cases such as POJO examples in Swagger documents. * *

* Setting applies to specified class and all subclasses. * *

Example:
*

* // Create a serializer that excludes the 'foo' and 'bar' properties on the MyBean class. * WriterSerializer serializer = JsonSerializer * .create() * .example(MyBean.class, "{foo:'bar'}") * .build(); *

* *

* This is a shorthand method for the following code: *

* builder.annotations(MarshalledAnnotation.create(pojoClass).example(json).build()) *

* *

* POJO examples can also be defined on classes via the following: *

    *
  • A static field annotated with {@link Example @Example}. *
  • A static method annotated with {@link Example @Example} with zero arguments or one {@link BeanSession} argument. *
  • A static method with name example with no arguments or one {@link BeanSession} argument. *
* *
See Also:
    *
  • {@link Marshalled#example()} *
* * @param The POJO class type. * @param pojoClass The POJO class. * @param json The JSON 5 representation of the example. * @return This object. */ @FluentSetter public Builder example(Class pojoClass, String json) { return annotations(MarshalledAnnotation.create(pojoClass).example(json).build()); } /** * Find fluent setters. * *

* When enabled, fluent setters are detected on beans during parsing. * *

* Fluent setters must have the following attributes: *

    *
  • Public. *
  • Not static. *
  • Take in one parameter. *
  • Return the bean itself. *
* *
Example:
*

* // A bean with a fluent setter. * public class MyBean { * public MyBean foo(String value) {...} * } * * // Create a parser that finds fluent setters. * ReaderParser parser = JsonParser * .create() * .findFluentSetters() * .build(); * * // Parse into bean using fluent setter. * MyBean myBean = parser.parse("{foo:'bar'}"); *

* *
Notes:
    *
  • The {@link Beanp @Beanp} annotation can also be used on methods to individually identify them as fluent setters. *
  • The {@link Bean#findFluentSetters() @Bean.fluentSetters()} annotation can also be used on classes to specify to look for fluent setters. *
* *
See Also:
    *
  • {@link org.apache.juneau.annotation.Bean#findFluentSetters()} *
  • {@link org.apache.juneau.annotation.BeanConfig#findFluentSetters()} *
* * @return This object. */ @FluentSetter public Builder findFluentSetters() { return findFluentSetters(true); } /** * Same as {@link #findFluentSetters()} but allows you to explicitly specify the value. * * @param value The value for this setting. * @return This object. */ @FluentSetter public Builder findFluentSetters(boolean value) { findFluentSetters = value; return this; } /** * Find fluent setters. * *

* Identical to {@link #findFluentSetters()} but enables it on a specific class only. * *

Example:
*

* // A bean with a fluent setter. * public class MyBean { * public MyBean foo(String value) {...} * } * * // Create a parser that finds fluent setters. * ReaderParser parser = JsonParser * .create() * .findFluentSetters(MyBean.class) * .build(); * * // Parse into bean using fluent setter. * MyBean myBean = parser.parse("{foo:'bar'}"); *

* *
Notes:
    *
  • This method is functionally equivalent to using the {@link Bean#findFluentSetters()} annotation. *
* *
See Also:
    *
  • {@link Bean#findFluentSetters()} *
  • {@link #findFluentSetters()} *
* * @param on The class that this applies to. * @return This object. */ @FluentSetter public Builder findFluentSetters(Class on) { return annotations(BeanAnnotation.create(on).findFluentSetters(true).build()); } /** * Ignore invocation errors on getters. * *

* When enabled, errors thrown when calling bean getter methods will silently be ignored. * Otherwise, a {@code BeanRuntimeException} is thrown. * *

Example:
*

* // A bean with a property that throws an exception. * public class MyBean { * public String getFoo() { * throw new RuntimeException("foo"); * } * } * * // Create a serializer that ignores bean getter exceptions. * WriterSerializer serializer = JsonSerializer * .create() * .ingoreInvocationExceptionsOnGetters() * .build(); * * // Exception is ignored. * String json = serializer.serialize(new MyBean()); *

* *
See Also:
    *
  • {@link org.apache.juneau.annotation.BeanConfig#ignoreInvocationExceptionsOnGetters()} *
* * @return This object. */ @FluentSetter public Builder ignoreInvocationExceptionsOnGetters() { return ignoreInvocationExceptionsOnGetters(true); } /** * Same as {@link #ignoreInvocationExceptionsOnGetters()} but allows you to explicitly specify the value. * * @param value The value for this setting. * @return This object. */ @FluentSetter public Builder ignoreInvocationExceptionsOnGetters(boolean value) { ignoreInvocationExceptionsOnGetters = value; return this; } /** * Ignore invocation errors on setters. * *

* When enabled, errors thrown when calling bean setter methods will silently be ignored. * Otherwise, a {@code BeanRuntimeException} is thrown. * *

Example:
*

* // A bean with a property that throws an exception. * public class MyBean { * public void setFoo(String foo) { * throw new RuntimeException("foo"); * } * } * * // Create a parser that ignores bean setter exceptions. * ReaderParser parser = JsonParser * .create() * .ignoreInvocationExceptionsOnSetters() * .build(); * * // Exception is ignored. * MyBean myBean = parser.parse("{foo:'bar'}", MyBean.class); *

* *
See Also:
    *
  • {@link org.apache.juneau.annotation.BeanConfig#ignoreInvocationExceptionsOnSetters()} *
* * @return This object. */ @FluentSetter public Builder ignoreInvocationExceptionsOnSetters() { return ignoreInvocationExceptionsOnSetters(true); } /** * Same as {@link #ignoreInvocationExceptionsOnSetters()} but allows you to explicitly specify the value. * * @param value The value for this setting. * @return This object. */ @FluentSetter public Builder ignoreInvocationExceptionsOnSetters(boolean value) { ignoreInvocationExceptionsOnSetters = value; return this; } /** * Don't silently ignore missing setters. * *

* 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. * *

Example:
*

* // A bean with a property with a getter but not a setter. * public class MyBean { * public void getFoo() { * return "foo"; * } * } * * // Create a parser that throws an exception if a setter is not found but a getter is. * ReaderParser parser = JsonParser * .create() * .disableIgnoreMissingSetters() * .build(); * * // Throws a ParseException. * MyBean myBean = parser.parse("{foo:'bar'}", MyBean.class); *

* *
Notes:
    *
  • The {@link BeanIgnore @BeanIgnore} annotation can also be used on getters and fields to ignore them. *
* *
See Also:
    *
  • {@link org.apache.juneau.annotation.BeanConfig#disableIgnoreMissingSetters()} *
* * @return This object. */ @FluentSetter public Builder disableIgnoreMissingSetters() { return disableIgnoreMissingSetters(true); } /** * Same as {@link #disableIgnoreMissingSetters()} but allows you to explicitly specify the value. * * @param value The value for this setting. * @return This object. */ @FluentSetter public Builder disableIgnoreMissingSetters(boolean value) { disableIgnoreMissingSetters = value; return this; } /** * Don't ignore transient fields. * *

* When enabled, methods and fields marked as transient will not be ignored as bean properties. * *

Example:
*

* // A bean with a transient field. * public class MyBean { * public transient String foo = "foo"; * } * * // Create a serializer that doesn't ignore transient fields. * WriterSerializer serializer = JsonSerializer * .create() * .disableIgnoreTransientFields() * .build(); * * // Produces: {"foo":"foo"} * String json = serializer.serialize(new MyBean()); *

* *
Notes:
    *
  • The {@link Beanp @Beanp} annotation can also be used on transient fields to keep them from being ignored. *
* *
See Also:
    *
  • {@link org.apache.juneau.annotation.BeanConfig#disableIgnoreTransientFields()} *
* * @return This object. */ @FluentSetter public Builder disableIgnoreTransientFields() { return disableIgnoreTransientFields(true); } /** * Same as {@link #disableIgnoreTransientFields()} but allows you to explicitly specify the value. * * @param value The value for this setting. * @return This object. */ @FluentSetter public Builder disableIgnoreTransientFields(boolean value) { disableIgnoreTransientFields = value; return this; } /** * Ignore unknown properties. * *

* When enabled, trying to set a value on a non-existent bean property will silently be ignored. * Otherwise, a {@code BeanRuntimeException} is thrown. * *

Example:
*

* // A bean with a single property. * public class MyBean { * public String foo; * } * * // Create a parser that ignores missing bean properties. * ReaderParser parser = JsonParser * .create() * .ignoreUnknownBeanProperties() * .build(); * * // Doesn't throw an exception on unknown 'bar' property. * MyBean myBean = parser.parse("{foo:'foo',bar:'bar'}", MyBean.class); *

* *
See Also:
    *
  • {@link org.apache.juneau.annotation.BeanConfig#ignoreUnknownBeanProperties()} *
* * @return This object. */ @FluentSetter public Builder ignoreUnknownBeanProperties() { return ignoreUnknownBeanProperties(true); } /** * Same as {@link #ignoreUnknownBeanProperties()} but allows you to explicitly specify the value. * * @param value The value for this setting. * @return This object. */ @FluentSetter public Builder ignoreUnknownBeanProperties(boolean value) { ignoreUnknownBeanProperties = value; return this; } /** * Ignore unknown properties. * *

* When enabled, unknown enum values will be set to null instead of throwing an exception. * *

See Also:
    *
  • {@link org.apache.juneau.annotation.BeanConfig#ignoreUnknownEnumValues()} *
* * @return This object. */ @FluentSetter public Builder ignoreUnknownEnumValues() { return ignoreUnknownEnumValues(true); } /** * Same as {@link #ignoreUnknownEnumValues()} but allows you to explicitly specify the value. * * @param value The value for this setting. * @return This object. */ @FluentSetter public Builder ignoreUnknownEnumValues(boolean value) { ignoreUnknownEnumValues = value; return this; } /** * Don't ignore unknown properties with null values. * *

* When enabled, trying to set a null value on a non-existent bean property will throw a {@link BeanRuntimeException}. * Otherwise it will be silently ignored. * *

Example:
*

* // A bean with a single property. * public class MyBean { * public String foo; * } * * // Create a parser that throws an exception on an unknown property even if the value being set is null. * ReaderParser parser = JsonParser * .create() * .disableIgnoreUnknownNullBeanProperties() * .build(); * * // Throws a BeanRuntimeException wrapped in a ParseException on the unknown 'bar' property. * MyBean myBean = parser.parse("{foo:'foo',bar:null}", MyBean.class); *

* *
See Also:
    *
  • {@link org.apache.juneau.annotation.BeanConfig#disableIgnoreUnknownNullBeanProperties()} *
* * @return This object. */ @FluentSetter public Builder disableIgnoreUnknownNullBeanProperties() { return disableIgnoreUnknownNullBeanProperties(true); } /** * Same as {@link #disableIgnoreUnknownNullBeanProperties()} but allows you to explicitly specify the value. * * @param value The value for this setting. * @return This object. */ @FluentSetter public Builder disableIgnoreUnknownNullBeanProperties(boolean value) { disableIgnoreUnknownNullBeanProperties = value; return this; } /** * Implementation classes. * *

* 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). * *

Example:
*

* // A bean interface. * public interface MyBean { * ... * } * * // A bean implementation. * public class MyBeanImpl implements MyBean { * ... * } * // Create a parser that instantiates MyBeanImpls when parsing MyBeans. * ReaderParser parser = JsonParser * .create() * .implClass(MyBean.class, MyBeanImpl.class) * .build(); * * // Instantiates a MyBeanImpl, * MyBean myBean = parser.parse("...", MyBean.class); *

* * @param interfaceClass The interface class. * @param implClass The implementation class. * @return This object. */ @FluentSetter public Builder implClass(Class interfaceClass, Class implClass) { return annotations(MarshalledAnnotation.create(interfaceClass).implClass(implClass).build()); } /** * Implementation classes. * *

* 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). * *

Example:
*

* // A bean with a single property. * public interface MyBean { * ... * } * * // A bean with a single property. * public class MyBeanImpl implements MyBean { * ... * } * // Create a parser that instantiates MyBeanImpls when parsing MyBeans. * ReaderParser parser = JsonParser * .create() * .implClasses(AMap.of(MyBean.class, MyBeanImpl.class)) * .build(); * * // Instantiates a MyBeanImpl, * MyBean myBean = parser.parse("...", MyBean.class); *

* * @param values * The new value for this setting. * @return This object. */ @FluentSetter public Builder implClasses(Map,Class> values) { values.forEach((k,v) -> annotations(MarshalledAnnotation.create(k).implClass(v).build())); return this; } /** * Identifies a class to be used as the interface class for the specified class and all subclasses. * *

* When specified, only the list of properties defined on the interface class will be used during serialization. * Additional properties on subclasses will be ignored. * *

* // Parent class or interface * public abstract class A { * public String foo = "foo"; * } * * // Sub class * public class A1 extends A { * public String bar = "bar"; * } * * // Create a serializer and define our interface class mapping. * WriterSerializer serializer = JsonSerializer * .create() * .interfaceClass(A1.class, A.class) * .build(); * * // Produces "{"foo":"foo"}" * String json = serializer.serialize(new A1()); *

* *

* 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. * *

Notes:
    *
  • The {@link Bean#interfaceClass() @Bean(interfaceClass)} annotation is the equivalent annotation-based solution. *
* * @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) { return annotations(BeanAnnotation.create(on).interfaceClass(value).build()); } /** * Identifies a set of interfaces. * *

* 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. * *

* // Parent class or interface * public abstract class A { * public String foo = "foo"; * } * * // Sub class * public class A1 extends A { * public String bar = "bar"; * } * * // Create a serializer and define our interface class mapping. * WriterSerializer serializer = JsonSerializer * .create() * .interfaces(A.class) * .build(); * * // Produces "{"foo":"foo"}" * String json = serializer.serialize(new A1()); *

* *

* 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. * *

Notes:
    *
  • The {@link Bean#interfaceClass() @Bean(interfaceClass)} annotation is the equivalent annotation-based solution. *
* * @param value * The new value for this setting. * @return This object. */ @FluentSetter public Builder interfaces(Class...value) { for (Class v : value) annotations(BeanAnnotation.create(v).interfaceClass(v).build()); return this; } /** * Context configuration property:  Locale. * *

* 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 Date and Calendar * 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. * *

Example:
*

* // Define a POJO swap that skips serializing beans if we're in the UK. * public class MyBeanSwap extends StringSwap<MyBean> { * @Override * public String swap(BeanSession session, MyBean bean) throws Exception { * if (session.getLocale().equals(Locale.UK)) * return null; * return bean.toString(); * } * } * * // Create a serializer that uses the specified locale if it's not passed in through session args. * WriterSerializer serializer = JsonSerializer * .create() * .locale(Locale.UK) * .swaps(MyBeanSwap.class) * .build(); *

* *
See Also:
    *
  • {@link org.apache.juneau.annotation.BeanConfig#locale()} *
  • {@link org.apache.juneau.BeanSession.Builder#locale(Locale)} *
* * @param value The new value for this property. * @return This object. */ @FluentSetter public Builder locale(Locale value) { locale = value; return this; } /** * Context configuration property:  Media type. * *

* 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 "application/json" * and "application/json+foo" slightly differently even though they're both being handled by the same JSON * serializer or parser. * *

Example:
*

* // Define a POJO swap that skips serializing beans if the media type is application/json. * public class MyBeanSwap extends StringSwap<MyBean> { * @Override * public String swap(BeanSession session, MyBean bean) throws Exception { * if (session.getMediaType().equals("application/json")) * return null; * return bean.toString(); * } * } * * // Create a serializer that uses the specified media type if it's not passed in through session args. * WriterSerializer serializer = JsonSerializer * .create() * .mediaType(MediaType.JSON) * .build(); *

* *
See Also:
    *
  • {@link org.apache.juneau.annotation.BeanConfig#mediaType()} *
  • {@link org.apache.juneau.BeanSession.Builder#mediaType(MediaType)} *
* * @param value The new value for this property. * @return This object. */ @FluentSetter public Builder mediaType(MediaType value) { mediaType = value; return this; } /** * Bean class exclusions. * *

* List of classes that should not be treated as beans even if they appear to be bean-like. * Not-bean classes are converted to Strings during serialization. * *

* Values can consist of any of the following types: *

    *
  • Classes. *
  • Arrays and collections of classes. *
* *
Example:
*

* // A bean with a single property. * public class MyBean { * public String foo = "bar"; * * public String toString() { * return "baz"; * } * } * * // Create a serializer that doesn't treat MyBean as a bean class. * WriterSerializer serializer = JsonSerializer * .create() * .notBeanClasses(MyBean.class) * .build(); * * // Produces "baz" instead of {"foo":"bar"} * String json = serializer.serialize(new MyBean()); *

* *
Notes:
    *
  • The {@link BeanIgnore @BeanIgnore} annotation can also be used on classes to prevent them from being recognized as beans. *
* *
See Also:
    *
  • {@link org.apache.juneau.annotation.BeanIgnore} *
  • {@link org.apache.juneau.annotation.BeanConfig#notBeanClasses()} *
* * @param values * The values to add to this setting. *
Values can consist of any of the following types: *
    *
  • Classes. *
  • Arrays and collections of classes. *
* @return This object. */ @FluentSetter public Builder notBeanClasses(Class...values) { return notBeanClasses(alist(values)); } /** * Same as {@link #notBeanClasses(Class...)} but allows you to pass in a collection of classes. * * @param values * The values to add to this setting. * @return This object. * @see #notBeanClasses(Class...) */ @FluentSetter public Builder notBeanClasses(Collection> values) { notBeanClasses().addAll(values); return this; } /** * Returns the list of not-bean classes. * *

* Gives access to the inner list if you need to make more than simple additions via {@link #notBeanClasses(Class...)}. * * @return The list of not-bean classes. * @see #notBeanClasses(Class...) */ public Set> notBeanClasses() { if (notBeanClasses == null) notBeanClasses = classSet(); return notBeanClasses; } /** * Bean package exclusions. * *

* Used as a convenient way of defining the {@link #notBeanClasses(Class...)} property for entire packages. * Any classes within these packages will be serialized to strings using {@link Object#toString()}. * *

* Note that you can specify suffix patterns to include all subpackages. * *

* Values can consist of any of the following types: *

    *
  • Strings. *
  • Arrays and collections of strings. *
* *
Example:
*

* // Create a serializer that ignores beans in the specified packages. * WriterSerializer serializer = JsonSerializer * .create() * .notBeanPackages("org.apache.foo", "org.apache.bar.*") * .build(); *

* * @param values * The values to add to this setting. *
Values can consist of any of the following types: *
    *
  • {@link Package} objects. *
  • Strings. *
  • Arrays and collections of anything in this list. *
* @return This object. */ @FluentSetter public Builder notBeanPackages(String...values) { return notBeanPackages(alist(values)); } /** * Same as {@link #notBeanPackages(String...)} but allows you to pass in a collection of classes. * * @param values * The values to add to this setting. * @return This object. * @see #notBeanPackages(String...) */ @FluentSetter public Builder notBeanPackages(Collection values) { notBeanPackages().addAll(values); return this; } /** * Returns the list of not-bean Java package names. * *

* Gives access to the inner list if you need to make more than simple additions via {@link #notBeanPackages(String...)}. * * @return The list of not-bean Java package names. * @see #notBeanPackages(String...) */ public Set notBeanPackages() { if (notBeanPackages == null) notBeanPackages = new TreeSet<>(); return notBeanPackages; } /** * Bean property namer * *

* The class to use for calculating bean property names. * *

* Predefined classes: *

    *
  • {@link BasicPropertyNamer} - Default. *
  • {@link PropertyNamerDLC} - Dashed-lower-case names. *
  • {@link PropertyNamerULC} - Dashed-upper-case names. *
* *
Example:
*

* // A bean with a single property. * public class MyBean { * public String fooBarBaz = "fooBarBaz"; * } * * // Create a serializer that uses Dashed-Lower-Case property names. * // (e.g. "foo-bar-baz" instead of "fooBarBaz") * WriterSerializer serializer = JsonSerializer * .create() * .propertyNamer(PropertyNamerDLC.class) * .build(); * * // Produces: {"foo-bar-baz":"fooBarBaz"} * String json = serializer.serialize(new MyBean()); *

* * @param value * The new value for this setting. *
The default is {@link BasicPropertyNamer}. * @return This object. */ @FluentSetter public Builder propertyNamer(Class value) { propertyNamer = value; return this; } /** * Bean property namer * *

* Same as {@link #propertyNamer(Class)} but allows you to specify a namer for a specific class. * *

Example:
*

* // A bean with a single property. * public class MyBean { * public String fooBarBaz = "fooBarBaz"; * } * * // Create a serializer that uses Dashed-Lower-Case property names for the MyBean class only. * // (e.g. "foo-bar-baz" instead of "fooBarBaz") * WriterSerializer serializer = JsonSerializer * .create() * .propertyNamer(MyBean.class, PropertyNamerDLC.class) * .build(); * * // Produces: {"foo-bar-baz":"fooBarBaz"} * String json = serializer.serialize(new MyBean()); *

* *
See Also:
    *
  • {@link Bean#propertyNamer() Bean(propertyNamer)} *
  • {@link #propertyNamer(Class)} *
* * @param on The class that the namer applies to. * @param value * The new value for this setting. *
The default is {@link BasicPropertyNamer}. * @return This object. */ @FluentSetter public Builder propertyNamer(Class on, Class value) { return annotations(BeanAnnotation.create(on).propertyNamer(value).build()); } /** * Sort bean properties. * *

* 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). * *

* 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. * *

Example:
*

* // A bean with 3 properties. * public class MyBean { * public String c = "1"; * public String b = "2"; * public String a = "3"; * } * * // Create a serializer that sorts bean properties. * WriterSerializer serializer = JsonSerializer * .create() * .sortProperties() * .build(); * * // Produces: {"a":"3","b":"2","c":"1"} * String json = serializer.serialize(new MyBean()); *

* *
Notes:
    *
  • The {@link Bean#sort() @Bean.sort()} annotation can also be used to sort properties on just a single class. *
* * @return This object. */ @FluentSetter public Builder sortProperties() { sortProperties = true; return sortProperties(true); } /** * Same as {@link #sortProperties()} but allows you to explicitly specify the value. * * @param value The value for this setting. * @return This object. */ @FluentSetter public Builder sortProperties(boolean value) { sortProperties = value; return this; } /** * Sort bean properties. * *

* Same as {@link #sortProperties()} but allows you to specify individual bean classes instead of globally. * *

Example:
*

* // A bean with 3 properties. * public class MyBean { * public String c = "1"; * public String b = "2"; * public String a = "3"; * } * * // Create a serializer that sorts properties on MyBean. * WriterSerializer serializer = JsonSerializer * .create() * .sortProperties(MyBean.class) * .build(); * * // Produces: {"a":"3","b":"2","c":"1"} * String json = serializer.serialize(new MyBean()); *

* *
See Also:
    *
  • {@link Bean#sort() Bean(sort)} *
  • {@link #sortProperties()} *
* * @param on The bean classes to sort properties on. * @return This object. */ @FluentSetter public Builder sortProperties(Class...on) { for (Class c : on) annotations(BeanAnnotation.create(c).sort(true).build()); return this; } /** * Identifies a stop class for the annotated class. * *

* 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. * *

* For example, in the following class hierarchy, instances of C3 will include property p3, * but not p1 or p2. * *

Example:
*

* public class C1 { * public int getP1(); * } * * public class C2 extends C1 { * public int getP2(); * } * * public class C3 extends C2 { * public int getP3(); * } * * // Create a serializer specifies a stop class for C3. * WriterSerializer serializer = JsonSerializer * .create() * .stopClass(C3.class, C2.class) * .build(); * * // Produces: {"p3":"..."} * String json = serializer.serialize(new C3()); *

* * @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) { return annotations(BeanAnnotation.create(on).stopClass(value).build()); } /** * Java object swaps. * *

* Swaps are used to "swap out" non-serializable classes with serializable equivalents during serialization, * and "swap in" the non-serializable class during parsing. * *

* An example of a swap would be a Calendar object that gets swapped out for an ISO8601 string. * *

* 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. * *

* Values can consist of any of the following types: *

    *
  • Any subclass of {@link ObjectSwap}. *
  • Any instance of {@link ObjectSwap}. *
  • Any surrogate class. A shortcut for defining a {@link SurrogateSwap}. *
  • Any array or collection of the objects above. *
* *
Example:
*

* // Sample swap for converting Dates to ISO8601 strings. * public class MyDateSwap extends StringSwap<Date> { * // ISO8601 formatter. * private DateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); * * @Override * public String swap(BeanSession session, Date date) { * return format.format(date); * } * * @Override * public Date unswap(BeanSession session, String string, ClassMeta hint) throws Exception { * return format.parse(string); * } * } * * // Sample bean with a Date field. * public class MyBean { * public Date date = new Date(112, 2, 3, 4, 5, 6); * } * * // Create a serializer that uses our date swap. * WriterSerializer serializer = JsonSerializer * .create() * .swaps(MyDateSwap.class) * .build(); * * // Produces: {"date":"2012-03-03T04:05:06-0500"} * String json = serializer.serialize(new MyBean()); * * // Create a serializer that uses our date swap. * ReaderParser parser = JsonParser * .create() * .swaps(MyDateSwap.class) * .build(); * * // Use our parser to parse a bean. * MyBean bean = parser.parse(json, MyBean.class); *

* *
Notes:
    *
  • The {@link Swap @Swap} annotation can also be used on classes to identify swaps for the class. *
  • The {@link Swap @Swap} annotation can also be used on bean methods and fields to identify swaps for values of those bean properties. *
* * @param values * The values to add to this setting. *
Values can consist of any of the following types: *
    *
  • Any subclass of {@link ObjectSwap}. *
  • Any surrogate class. A shortcut for defining a {@link SurrogateSwap}. *
  • Any array or collection of the objects above. *
* @return This object. */ @FluentSetter public Builder swaps(Class...values) { return swaps(alist(values)); } /** * Same as {@link #swaps(Class...)} but allows you to pass in a collection of classes. * * @param values * The values to add to this setting. * @return This object. * @see #swaps(Class...) */ @FluentSetter public Builder swaps(Collection> values) { swaps().addAll(0, values); return this; } /** * A shortcut for defining a {@link FunctionalSwap}. * *
Example:
*

* // Create a serializer that performs a custom format for DAte objects. * WriterSerializer serializer = JsonSerializer * .create() * .swap(Date.class, String.class, x -> format(x)) * .build(); *

* * @param The object type being swapped out. * @param 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 Builder swap(Class normalClass, Class swappedClass, ThrowingFunction swapFunction) { return swap(normalClass, swappedClass, swapFunction, null); } /** * A shortcut for defining a {@link FunctionalSwap}. * *
Example:
*

* // Create a serializer that performs a custom format for Date objects. * WriterSerializer serializer = JsonSerializer * .create() * .swap(Date.class, String.class, x -> format(x), x -> parse(x)) * .build(); *

* * @param The object type being swapped out. * @param 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 Builder swap(Class normalClass, Class swappedClass, ThrowingFunction swapFunction, ThrowingFunction unswapFunction) { swaps().add(0, new FunctionalSwap<>(normalClass, swappedClass, swapFunction, unswapFunction)); return this; } /** * Returns the bean swaps list. * *

* Gives access to the inner list if you need to make more than simple additions via {@link #swaps(Class...)}. * * @return The bean swaps list. * @see #swaps(Class...) */ public List swaps() { if (swaps == null) swaps = list(); return swaps; } /** * Context configuration property:  TimeZone. * *

* 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 Date and Calendar * 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. * *

Example:
*

* // Define a POJO swap that skips serializing beans if the time zone is GMT. * public class MyBeanSwap extends StringSwap<MyBean> { * @Override * public String swap(BeanSession session, MyBean bean) throws Exception { * if (session.getTimeZone().equals(TimeZone.GMT)) * return null; * return bean.toString(); * } * } * * // Create a serializer that uses GMT if the timezone is not specified in the session args. * WriterSerializer serializer = JsonSerializer * .create() * .timeZone(TimeZone.GMT) * .build(); *

* *
See Also:
    *
  • {@link org.apache.juneau.annotation.BeanConfig#timeZone()} *
  • {@link org.apache.juneau.BeanSession.Builder#timeZone(TimeZone)} *
* * @param value The new value for this property. * @return This object. */ @FluentSetter public Builder timeZone(TimeZone value) { timeZone = value; return this; } /** * An identifying name for this class. * *

* 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 Object, then the serializer will add the name to the * output so that the class can be determined during parsing. * *

* It is also used to specify element names in XML. * *

Example:
*

* // Use _type='mybean' to identify this bean. * public class MyBean {...} * * // Create a serializer and specify the type name.. * WriterSerializer serializer = JsonSerializer * .create() * .typeName(MyBean.class, "mybean") * .build(); * * // Produces: {"_type":"mybean",...} * String json = serializer.serialize(new MyBean()); *

* *
Notes:
    *
  • Equivalent to the {@link Bean#typeName() Bean(typeName)} annotation. *
* *
See Also:
    *
  • {@link Bean#typeName() Bean(typeName)} *
  • {@link #beanDictionary(Class...)} *
* * @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) { return annotations(BeanAnnotation.create(on).typeName(value).build()); } /** * Bean type property name. * *

* 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. * *

Example:
*

* // POJOs with @Bean(name) annotations. * @Bean(typeName="foo") * public class Foo {...} * @Bean(typeName="bar") * public class Bar {...} * * // Create a serializer that uses 't' instead of '_type' for dictionary names. * WriterSerializer serializer = JsonSerializer * .create() * .typePropertyName("t") * .dictionary(Foo.class, Bar.class) * .build(); * * // Create a serializer that uses 't' instead of '_type' for dictionary names. * ReaderParser parser = JsonParser * .create() * .typePropertyName("t") * .dictionary(Foo.class, Bar.class) * .build(); * * // A bean with a field with an indeterminate type. * public class MyBean { * public Object mySimpleField; * } * * // Produces "{mySimpleField:{t:'foo',...}}". * String json = serializer.serialize(new MyBean()); * * // Parse bean. * MyBean bean = parser.parse(json, MyBean.class); *

* *
See Also:
    *
  • {@link org.apache.juneau.annotation.Bean#typePropertyName()} *
  • {@link org.apache.juneau.annotation.BeanConfig#typePropertyName()} *
* * @param value * The new value for this setting. *
The default is "_type". * @return This object. */ @FluentSetter public Builder typePropertyName(String value) { typePropertyName = value; return this; } /** * Bean type property name. * *

* Same as {@link #typePropertyName(String)} except targets a specific bean class instead of globally. * *

Example:
*

* // POJOs with @Bean(name) annotations. * @Bean(typeName="foo") * public class Foo {...} * @Bean(typeName="bar") * public class Bar {...} * * // A bean with a field with an indeterminate type. * public class MyBean { * public Object mySimpleField; * } * * // Create a serializer that uses 't' instead of '_type' for dictionary names. * WriterSerializer serializer = JsonSerializer * .create() * .typePropertyName(MyBean.class, "t") * .dictionary(Foo.class, Bar.class) * .build(); * * // Produces "{mySimpleField:{t:'foo',...}}". * String json = serializer.serialize(new MyBean()); *

* *
See Also:
    *
  • {@link Bean#typePropertyName() Bean(typePropertyName)} *
* * @param on The class the type property name applies to. * @param value * The new value for this setting. *
The default is "_type". * @return This object. */ @FluentSetter public Builder typePropertyName(Class on, String value) { return annotations(BeanAnnotation.create(on).typePropertyName(value).build()); } /** * Use enum names. * *

* When enabled, enums are always serialized by name, not using {@link Object#toString()}. * *

Example:
*

* // Create a serializer with debug enabled. * WriterSerializer serializer = JsonSerializer * .create() * .useEnumNames() * .build(); * * // Enum with overridden toString(). * // Will be serialized as ONE/TWO/THREE even though there's a toString() method. * public enum Option { * ONE(1), * TWO(2), * THREE(3); * * private int value; * * Option(int value) { * this.value = value; * } * * @Override * public String toString() { * return String.valueOf(value); * } * } *

* * @return This object. */ @FluentSetter public Builder useEnumNames() { return useEnumNames(true); } /** * Same as {@link #useEnumNames()} but allows you to explicitly specify the value. * * @param value The value for this setting. * @return This object. */ @FluentSetter public Builder useEnumNames(boolean value) { useEnumNames = value; return this; } /** * Don't use interface proxies. * *

* 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}. * *

See Also:
    *
  • {@link org.apache.juneau.annotation.BeanConfig#disableInterfaceProxies()} *
* * @return This object. */ @FluentSetter public Builder disableInterfaceProxies() { return disableInterfaceProxies(true); } /** * Same as {@link #disableInterfaceProxies()} but allows you to explicitly specify the value. * * @param value The value for this setting. * @return This object. */ @FluentSetter public Builder disableInterfaceProxies(boolean value) { disableInterfaceProxies = value; return this; } /** * Use Java Introspector. * *

* Using the built-in Java bean introspector will not pick up fields or non-standard getters/setters. *
Most {@link Bean @Bean} annotations will be ignored. * *

Example:
*

* // Create a serializer that only uses the built-in java bean introspector for finding properties. * WriterSerializer serializer = JsonSerializer * .create() * .useJavaBeanIntrospector() * .build(); *

* * @return This object. */ @FluentSetter public Builder useJavaBeanIntrospector() { return useJavaBeanIntrospector(true); } /** * Same as {@link #useJavaBeanIntrospector()} but allows you to explicitly specify the value. * * @param value The value for this setting. * @return This object. */ @FluentSetter public Builder useJavaBeanIntrospector(boolean value) { useJavaBeanIntrospector = value; return this; } // @Override /* GENERATED - org.apache.juneau.Context.Builder */ public Builder annotations(Annotation...values) { super.annotations(values); return this; } @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 value) { super.cache(value); return this; } @Override /* GENERATED - org.apache.juneau.Context.Builder */ public Builder debug() { super.debug(); return this; } @Override /* GENERATED - org.apache.juneau.Context.Builder */ public Builder debug(boolean value) { super.debug(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 value) { super.type(value); return this; } // //----------------------------------------------------------------------------------------------------------------- // Helpers //----------------------------------------------------------------------------------------------------------------- private static Set> classSet() { return new TreeSet<>(Comparator.comparing(Class::getName)); } private static Set> classSet(Collection> copy) { return classSet(copy, false); } private static Set> classSet(Collection> copy, boolean nullIfEmpty) { if (copy == null || (nullIfEmpty && copy.isEmpty())) return null; Set> x = classSet(); x.addAll(copy); return x; } } //----------------------------------------------------------------------------------------------------------------- // Instance //----------------------------------------------------------------------------------------------------------------- final boolean beansRequireDefaultConstructor, beansRequireSerializable, beansRequireSettersForGetters, beansRequireSomeProperties, beanMapPutReturnsOldValue, useInterfaceProxies, ignoreUnknownBeanProperties, ignoreUnknownNullBeanProperties, ignoreUnknownEnumValues, ignoreMissingSetters, ignoreTransientFields, ignoreInvocationExceptionsOnGetters, ignoreInvocationExceptionsOnSetters, useJavaBeanIntrospector, useEnumNames, sortProperties, findFluentSetters; final Visibility beanConstructorVisibility, beanClassVisibility, beanMethodVisibility, beanFieldVisibility; final String typePropertyName; final Locale locale; final TimeZone timeZone; final MediaType mediaType; final Class propertyNamer; final List> beanDictionary, notBeanClasses; final List swaps; final List notBeanPackages; final HashKey hashKey; final Map cmCache; private final String[] notBeanPackageNames, notBeanPackagePrefixes; private final BeanRegistry beanRegistry; private final PropertyNamer propertyNamerBean; private final ObjectSwap[] swapArray; private final Class[] notBeanClassesArray; private final ClassMeta cmObject; // Reusable ClassMeta that represents general Objects. private final ClassMeta cmString; // Reusable ClassMeta that represents general Strings. private final ClassMeta cmClass; // Reusable ClassMeta that represents general Classes. private final BeanSession defaultSession; private volatile WriterSerializer beanToStringSerializer; /** * Constructor. * * @param builder The builder for this object. */ public BeanContext(Builder builder) { super(builder); hashKey = builder.hashKey(); beanConstructorVisibility = builder.beanConstructorVisibility; beanClassVisibility = builder.beanClassVisibility; beanMethodVisibility = builder.beanMethodVisibility; beanFieldVisibility = builder.beanFieldVisibility; beansRequireDefaultConstructor = builder.beansRequireDefaultConstructor; beansRequireSerializable = builder.beansRequireSerializable; beansRequireSettersForGetters = builder.beansRequireSettersForGetters; beansRequireSomeProperties = ! builder.disableBeansRequireSomeProperties; beanMapPutReturnsOldValue = builder.beanMapPutReturnsOldValue; useEnumNames = builder.useEnumNames; useInterfaceProxies = ! builder.disableInterfaceProxies; ignoreUnknownBeanProperties = builder.ignoreUnknownBeanProperties; ignoreUnknownNullBeanProperties = ! builder.disableIgnoreUnknownNullBeanProperties; ignoreUnknownEnumValues = builder.ignoreUnknownEnumValues; ignoreMissingSetters = ! builder.disableIgnoreMissingSetters; ignoreTransientFields = ! builder.disableIgnoreTransientFields; ignoreInvocationExceptionsOnGetters = builder.ignoreInvocationExceptionsOnGetters; ignoreInvocationExceptionsOnSetters = builder.ignoreInvocationExceptionsOnSetters; useJavaBeanIntrospector = builder.useJavaBeanIntrospector; sortProperties = builder.sortProperties; findFluentSetters = builder.findFluentSetters; typePropertyName = builder.typePropertyName != null ? builder.typePropertyName : "_type"; locale = builder.locale != null ? builder.locale : Locale.getDefault(); timeZone = builder.timeZone; mediaType = builder.mediaType; beanDictionary = optional(builder.beanDictionary).map(Collections::unmodifiableList).orElse(emptyList()); swaps = optional(builder.swaps).map(Collections::unmodifiableList).orElse(emptyList()); notBeanClasses = optional(builder.notBeanClasses).map(ArrayList::new).map(Collections::unmodifiableList).orElse(emptyList()); notBeanPackages = optional(builder.notBeanPackages).map(ArrayList::new).map(Collections::unmodifiableList).orElse(emptyList()); propertyNamer = builder.propertyNamer != null ? builder.propertyNamer : BasicPropertyNamer.class; notBeanClassesArray = notBeanClasses.isEmpty() ? DEFAULT_NOTBEAN_CLASSES : Stream.of(notBeanClasses, alist(DEFAULT_NOTBEAN_CLASSES)).flatMap(Collection::stream).toArray(Class[]::new); String[] _notBeanPackages = notBeanPackages.isEmpty() ? DEFAULT_NOTBEAN_PACKAGES : Stream.of(notBeanPackages, alist(DEFAULT_NOTBEAN_PACKAGES)).flatMap(Collection::stream).toArray(String[]::new); notBeanPackageNames = Stream.of(_notBeanPackages).filter(x -> ! x.endsWith(".*")).toArray(String[]::new); notBeanPackagePrefixes = Stream.of(_notBeanPackages).filter(x -> x.endsWith(".*")).map(x -> x.substring(0, x.length()-2)).toArray(String[]::new); try { propertyNamerBean = propertyNamer.getDeclaredConstructor().newInstance(); } catch (Exception e) { throw asRuntimeException(e); } LinkedList> _swaps = new LinkedList<>(); swaps.forEach(x -> { if (x instanceof ObjectSwap) { _swaps.add((ObjectSwap)x); } else { ClassInfo ci = ClassInfo.of((Class)x); if (ci.isChildOf(ObjectSwap.class)) _swaps.add(BeanCreator.of(ObjectSwap.class).type(ci).run()); else if (ci.isChildOf(Surrogate.class)) _swaps.addAll(SurrogateSwap.findObjectSwaps(ci.inner(), this)); else throw new BasicRuntimeException("Invalid class {0} specified in BeanContext.swaps property. Must be a subclass of ObjectSwap or Surrogate.", ci.inner()); } }); swapArray = _swaps.toArray(new ObjectSwap[_swaps.size()]); cmCache = new ConcurrentHashMap<>(); cmCache.put(String.class, new ClassMeta(String.class, this, findObjectSwaps(String.class), findChildObjectSwaps(String.class))); cmCache.put(Object.class, new ClassMeta(Object.class, this, findObjectSwaps(Object.class), findChildObjectSwaps(Object.class))); cmString = cmCache.get(String.class); cmObject = cmCache.get(Object.class); cmClass = cmCache.get(Class.class); beanRegistry = new BeanRegistry(this, null); defaultSession = createSession().unmodifiable().build(); } @Override /* Context */ public Builder copy() { return new Builder(this); } @Override /* Context */ public BeanSession.Builder createSession() { return BeanSession.create(this); } @Override /* Context */ public BeanSession getSession() { return defaultSession; } /** * Returns true if the specified bean context shares the same cache as this bean context. * *

* Useful for testing purposes. * * @param bc The bean context to compare to. * @return true if the bean contexts have equivalent settings and thus share caches. */ public final boolean hasSameCache(BeanContext bc) { return bc.cmCache == this.cmCache; } /** * Wraps an object inside a {@link BeanMap} object (a modifiable {@link Map}). * *

* This is a shortcut for the following code: createSession().build().toBeanMap(object); * *

Example:
*

* // Construct a bean map around a bean instance * BeanMap<Person> beanMap = BeanContext.DEFAULT.toBeanMap(new Person()); *

* * @param The class of the object being wrapped. * @param object The object to wrap in a map interface. Must not be null. * @return The wrapped object. * @see BeanSession#toBeanMap(Object) */ public BeanMap toBeanMap(T object) { return defaultSession.toBeanMap(object); } /** * Creates a new {@link BeanMap} object (a modifiable {@link Map}) of the given class with uninitialized * property values. * *

* This is a shortcut for the following code: createSession().build().newBeanMap(_class); * *

Example:
*

* // Construct a new bean map wrapped around a new Person object * BeanMap<Person> beanMap = BeanContext.DEFAULT.newBeanMap(Person.class); *

* * @param The class of the object being wrapped. * @param c The name of the class to create a new instance of. * @return A new instance of the class. * @see BeanSession#newBeanMap(Class) */ public BeanMap newBeanMap(Class c) { return defaultSession.newBeanMap(c); } /** * Converts the specified value to the specified class type. * *

* This is a shortcut for the following code: createSession().build().convertToType(value, type); * * @param The class type to convert the value to. * @param value The value to convert. * @param type The class type to convert the value to. * @throws InvalidDataConversionException If the specified value cannot be converted to the specified type. * @return The converted value. * @see BeanSession#convertToType(Object, Class) */ public final T convertToType(Object value, Class type) throws InvalidDataConversionException { return defaultSession.convertToType(value, type); } /** * Same as {@link #convertToType(Object, Class)}, except used for instantiating inner member classes that must * be instantiated within another class instance. * *

* This is a shortcut for the following code: createSession().build().convertToMemberType(outer, value, type); * * @param The class type to convert the value to. * @param outer * If class is a member class, this is the instance of the containing class. * Should be null if not a member class. * @param value The value to convert. * @param type The class type to convert the value to. * @throws InvalidDataConversionException If the specified value cannot be converted to the specified type. * @return The converted value. * @see BeanSession#convertToMemberType(Object, Object, Class) */ public final T convertToMemberType(Object outer, Object value, Class type) throws InvalidDataConversionException { return defaultSession.convertToMemberType(outer, value, getClassMeta(type)); } /** * Same as {@link #convertToType(Object, Class)}, but allows for complex data types consisting of collections or maps. * *

* This is a shortcut for the following code: createSession().build().convertToType(value, type, args); * * @param The class type to convert the value to. * @param value The value to be converted. * @param type The target object type. * @param args The target object parameter types. * @return The converted type. * @throws InvalidDataConversionException If the specified value cannot be converted to the specified type. * @see BeanSession#convertToType(Object, Type, Type...) */ public final T convertToType(Object value, Type type, Type...args) throws InvalidDataConversionException { return (T)defaultSession.convertToMemberType(null, value, getClassMeta(type, args)); } /** * Determines whether the specified class is ignored as a bean class based on the various exclusion parameters * specified on this context class. * * @param c The class type being tested. * @return true if the specified class matches any of the exclusion parameters. */ protected final boolean isNotABean(Class c) { if (c.isArray() || c.isPrimitive() || c.isEnum() || c.isAnnotation()) return true; Package p = c.getPackage(); if (p != null) { for (String p2 : notBeanPackageNames) if (p.getName().equals(p2)) return true; for (String p2 : notBeanPackagePrefixes) if (p.getName().startsWith(p2)) return true; } ClassInfo ci = ClassInfo.of(c); for (Class exclude : notBeanClassesArray) if (ci.isChildOf(exclude)) return true; return false; } /** * Returns true if the specified object is a bean. * * @param o The object to test. * @return true if the specified object is a bean. false if the bean is null. */ public boolean isBean(Object o) { if (o == null) return false; return getClassMetaForObject(o).isBean(); } /** * Returns the {@link BeanMeta} class for the specified class. * * @param The class type to get the meta-data on. * @param c The class to get the meta-data on. * @return * The {@link BeanMeta} for the specified class, or null if the class is not a bean per the settings on * this context. */ public final BeanMeta getBeanMeta(Class c) { if (c == null) return null; return getClassMeta(c).getBeanMeta(); } /** * Construct a {@code ClassMeta} wrapper around a {@link Class} object. * * @param The class type being wrapped. * @param type The class to resolve. * @return * If the class is not an array, returns a cached {@link ClassMeta} object. * Otherwise, returns a new {@link ClassMeta} object every time. */ public final ClassMeta getClassMeta(Class type) { return getClassMeta(type, true); } /** * Construct a {@code ClassMeta} wrapper around a {@link Class} object. * * @param The class type being wrapped. * @param type The class to resolve. * @param waitForInit * When enabled, wait for the ClassMeta constructor to finish before returning. * @return * If the class is not an array, returns a cached {@link ClassMeta} object. * Otherwise, returns a new {@link ClassMeta} object every time. */ final ClassMeta getClassMeta(Class type, boolean waitForInit) { // This can happen if we have transforms defined against String or Object. if (cmCache == null) return null; ClassMeta cm = cmCache.get(type); if (cm == null) { synchronized (this) { // Make sure someone didn't already set it while this thread was blocked. cm = cmCache.get(type); if (cm == null) cm = new ClassMeta<>(type, this, findObjectSwaps(type), findChildObjectSwaps(type)); } } if (waitForInit) cm.waitForInit(); return cm; } /** * Used to resolve ClassMetas of type Collection and Map that have * ClassMeta values that themselves could be collections or maps. * *

* Collection meta objects are assumed to be followed by zero or one meta objects indicating the element type. * *

* Map meta objects are assumed to be followed by zero or two meta objects indicating the key and value types. * *

* The array can be arbitrarily long to indicate arbitrarily complex data structures. * *

Examples:
*
    *
  • getClassMeta(String.class); - A normal type. *
  • getClassMeta(List.class); - A list containing objects. *
  • getClassMeta(List.class, String.class); - A list containing strings. *
  • getClassMeta(LinkedList.class, String.class); - A linked-list containing * strings. *
  • getClassMeta(LinkedList.class, LinkedList.class, String.class); - * A linked-list containing linked-lists of strings. *
  • getClassMeta(Map.class); - A map containing object keys/values. *
  • getClassMeta(Map.class, String.class, String.class); - A map * containing string keys/values. *
  • getClassMeta(Map.class, String.class, List.class, MyBean.class); - * A map containing string keys and values of lists containing beans. *
* * @param * The class to resolve. * @param type * The class to resolve. *
Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType} * @param args * The type arguments of the class if it's a collection or map. *
Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType} *
Ignored if the main type is not a map or collection. * @return The resolved class meta. */ public final ClassMeta getClassMeta(Type type, Type...args) { if (type == null) return null; ClassMeta cm = type instanceof Class ? getClassMeta((Class)type) : resolveClassMeta(type, null); if (args.length == 0) return cm; ClassMeta[] cma = new ClassMeta[args.length+1]; cma[0] = cm; for (int i = 0; i < Array.getLength(args); i++) { Type arg = (Type)Array.get(args, i); cma[i+1] = arg instanceof Class ? getClassMeta((Class)arg) : resolveClassMeta(arg, null); } return (ClassMeta) getTypedClassMeta(cma, 0); } /* * Resolves the 'genericized' class meta at the specified position in the ClassMeta array. */ private ClassMeta getTypedClassMeta(ClassMeta[] c, int pos) { ClassMeta cm = c[pos++]; if (cm.isCollection() || cm.isOptional()) { ClassMeta ce = c.length == pos ? object() : getTypedClassMeta(c, pos); return (ce.isObject() ? cm : new ClassMeta(cm, null, null, ce)); } else if (cm.isMap()) { ClassMeta ck = c.length == pos ? object() : c[pos++]; ClassMeta cv = c.length == pos ? object() : getTypedClassMeta(c, pos); return (ck.isObject() && cv.isObject() ? cm : new ClassMeta(cm, ck, cv, null)); } return cm; } final ClassMeta resolveClassMeta(Type o, Map,Class[]> typeVarImpls) { if (o == null) return null; if (o instanceof ClassMeta) { ClassMeta cm = (ClassMeta)o; // This classmeta could have been created by a different context. // Need to re-resolve it to pick up ObjectSwaps and stuff on this context. if (cm.getBeanContext() == this) return cm; if (cm.isMap()) return getClassMeta(cm.innerClass, cm.getKeyType(), cm.getValueType()); if (cm.isCollection() || cm.isOptional()) return getClassMeta(cm.innerClass, cm.getElementType()); return getClassMeta(cm.innerClass); } Class c = resolve(o, typeVarImpls); // This can happen when trying to resolve the "E getFirst()" method on LinkedList, whose type is a TypeVariable // These should just resolve to Object. if (c == null) return object(); ClassMeta rawType = getClassMeta(c); // If this is a Map or Collection, and the parameter types aren't part // of the class definition itself (e.g. class AddressBook extends List), // then we need to figure out the parameters. if (rawType.isMap() || rawType.isCollection() || rawType.isOptional()) { ClassMeta[] params = findParameters(o, c); if (params == null) return rawType; if (rawType.isMap()) { if (params.length != 2 || (params[0].isObject() && params[1].isObject())) return rawType; return new ClassMeta(rawType, params[0], params[1], null); } if (rawType.isCollection() || rawType.isOptional()) { if (params.length != 1 || params[0].isObject()) return rawType; return new ClassMeta(rawType, null, null, params[0]); } } if (rawType.isArray()) { if (o instanceof GenericArrayType) { GenericArrayType gat = (GenericArrayType)o; ClassMeta elementType = resolveClassMeta(gat.getGenericComponentType(), typeVarImpls); return new ClassMeta(rawType, null, null, elementType); } } return rawType; } /** * Convert a Type to a Class if possible. * Return null if not possible. */ final Class resolve(Type t, Map,Class[]> typeVarImpls) { if (t instanceof Class) return (Class)t; if (t instanceof ParameterizedType) // A parameter (e.g. . return (Class)((ParameterizedType)t).getRawType(); if (t instanceof GenericArrayType) { // An array parameter (e.g. ). Type gatct = ((GenericArrayType)t).getGenericComponentType(); if (gatct instanceof Class) return Array.newInstance((Class)gatct, 0).getClass(); if (gatct instanceof ParameterizedType) return Array.newInstance((Class)((ParameterizedType)gatct).getRawType(), 0).getClass(); if (gatct instanceof GenericArrayType) return Array.newInstance(resolve(gatct, typeVarImpls), 0).getClass(); return null; } else if (t instanceof TypeVariable) { if (typeVarImpls != null) { TypeVariable tv = (TypeVariable)t; String varName = tv.getName(); int varIndex = -1; Class gc = (Class)tv.getGenericDeclaration(); TypeVariable[] tvv = gc.getTypeParameters(); for (int i = 0; i < tvv.length; i++) { if (tvv[i].getName().equals(varName)) { varIndex = i; } } if (varIndex != -1) { // If we couldn't find a type variable implementation, that means // the type was defined at runtime (e.g. Bean b = new Bean();) // in which case the type is lost through erasure. // Assume java.lang.Object as the type. if (! typeVarImpls.containsKey(gc)) return null; return typeVarImpls.get(gc)[varIndex]; } } } return null; } final ClassMeta[] findParameters(Type o, Class c) { if (o == null) o = c; // Loop until we find a ParameterizedType if (! (o instanceof ParameterizedType)) { loop: do { o = c.getGenericSuperclass(); if (o instanceof ParameterizedType) break loop; for (Type t : c.getGenericInterfaces()) { o = t; if (o instanceof ParameterizedType) break loop; } c = c.getSuperclass(); } while (c != null); } if (o instanceof ParameterizedType) { ParameterizedType pt = (ParameterizedType)o; if (! pt.getRawType().equals(Enum.class)) { List> l = new LinkedList<>(); for (Type pt2 : pt.getActualTypeArguments()) { if (pt2 instanceof WildcardType || pt2 instanceof TypeVariable) return null; l.add(resolveClassMeta(pt2, null)); } if (l.isEmpty()) return null; return l.toArray(new ClassMeta[l.size()]); } } return null; } /** * Shortcut for calling {@code getClassMeta(o.getClass())}. * * @param The class of the object being passed in. * @param o The class to find the class type for. * @return The ClassMeta object, or null if {@code o} is null. */ public final ClassMeta getClassMetaForObject(T o) { if (o == null) return null; return (ClassMeta)getClassMeta(o.getClass()); } /** * Used for determining the class type on a method or field where a {@code @Beanp} annotation may be present. * * @param The class type we're wrapping. * @param p The property annotation on the type if there is one. * @param t The type. * @param typeVarImpls * Contains known resolved type parameters on the specified class so that we can result * {@code ParameterizedTypes} and {@code TypeVariables}. * Can be null if the information is not known. * @return The new {@code ClassMeta} object wrapped around the {@code Type} object. */ protected final ClassMeta resolveClassMeta(Beanp p, Type t, Map,Class[]> typeVarImpls) { ClassMeta cm = resolveClassMeta(t, typeVarImpls); ClassMeta cm2 = cm; if (p != null) { if (isNotVoid(p.type())) cm2 = resolveClassMeta(p.type(), typeVarImpls); if (cm2.isMap()) { Class[] pParams = (p.params().length == 0 ? new Class[]{Object.class, Object.class} : p.params()); if (pParams.length != 2) throw new BasicRuntimeException("Invalid number of parameters specified for Map (must be 2): {0}", pParams.length); ClassMeta keyType = resolveType(pParams[0], cm2.getKeyType(), cm.getKeyType()); ClassMeta valueType = resolveType(pParams[1], cm2.getValueType(), cm.getValueType()); if (keyType.isObject() && valueType.isObject()) return cm2; return new ClassMeta<>(cm2, keyType, valueType, null); } if (cm2.isCollection() || cm2.isOptional()) { Class[] pParams = (p.params().length == 0 ? new Class[]{Object.class} : p.params()); if (pParams.length != 1) throw new BasicRuntimeException("Invalid number of parameters specified for {1} (must be 1): {0}", pParams.length, (cm2.isCollection() ? "Collection" : cm2.isOptional() ? "Optional" : "Array")); ClassMeta elementType = resolveType(pParams[0], cm2.getElementType(), cm.getElementType()); if (elementType.isObject()) return cm2; return new ClassMeta<>(cm2, null, null, elementType); } return cm2; } return cm; } private ClassMeta resolveType(Type...t) { for (Type tt : t) { if (tt != null) { ClassMeta cm = getClassMeta(tt); if (tt != cmObject) return cm; } } return cmObject; } /** * Returns the {@link ObjectSwap} associated with the specified class, or null if there is no POJO swap * associated with the class. * * @param The class associated with the swap. * @param c The class associated with the swap. * @return The swap associated with the class, or null if there is no association. */ private final ObjectSwap[] findObjectSwaps(Class c) { // Note: On first if (c != null) { List l = list(); for (ObjectSwap f : swapArray) if (f.getNormalClass().isParentOf(c)) l.add(f); return l.size() == 0 ? null : l.toArray(new ObjectSwap[l.size()]); } return null; } /** * Checks whether a class has a {@link ObjectSwap} associated with it in this bean context. * * @param c The class to check. * @return true if the specified class or one of its subclasses has a {@link ObjectSwap} associated with it. */ private final ObjectSwap[] findChildObjectSwaps(Class c) { if (c == null || swapArray.length == 0) return null; List l = null; for (ObjectSwap f : swapArray) { if (f.getNormalClass().isChildOf(c)) { if (l == null) l = list(); l.add(f); } } return l == null ? null : l.toArray(new ObjectSwap[l.size()]); } /** * Returns a reusable {@link ClassMeta} representation for the class Object. * *

* This ClassMeta is often used to represent "any object type" when an object type is not known. * *

* This method is identical to calling getClassMeta(Object.class) but uses a cached copy to * avoid a hashmap lookup. * * @return The {@link ClassMeta} object associated with the Object class. */ protected final ClassMeta object() { return cmObject; } /** * Returns a reusable {@link ClassMeta} representation for the class String. * *

* This ClassMeta is often used to represent key types in maps. * *

* This method is identical to calling getClassMeta(String.class) but uses a cached copy to * avoid a hashmap lookup. * * @return The {@link ClassMeta} object associated with the String class. */ protected final ClassMeta string() { return cmString; } /** * Returns a reusable {@link ClassMeta} representation for the class Class. * *

* This ClassMeta is often used to represent key types in maps. * *

* This method is identical to calling getClassMeta(Class.class) but uses a cached copy to * avoid a hashmap lookup. * * @return The {@link ClassMeta} object associated with the String class. */ protected final ClassMeta _class() { return cmClass; } /** * Returns the lookup table for resolving bean types by name. * * @return The lookup table for resolving bean types by name. */ protected final BeanRegistry getBeanRegistry() { return beanRegistry; } //----------------------------------------------------------------------------------------------------------------- // Properties //----------------------------------------------------------------------------------------------------------------- /** * Minimum bean class visibility. * * @see BeanContext.Builder#beanClassVisibility(Visibility) * @return * Classes are not considered beans unless they meet the minimum visibility requirements. */ public final Visibility getBeanClassVisibility() { return beanClassVisibility; } /** * Minimum bean constructor visibility. * * @see BeanContext.Builder#beanConstructorVisibility(Visibility) * @return * Only look for constructors with this specified minimum visibility. */ public final Visibility getBeanConstructorVisibility() { return beanConstructorVisibility; } /** * Bean dictionary. * * @see BeanContext.Builder#beanDictionary() * @return * The list of classes that make up the bean dictionary in this bean context. */ public final List> getBeanDictionary() { return beanDictionary; } /** * Minimum bean field visibility. * * * @see BeanContext.Builder#beanFieldVisibility(Visibility) * @return * Only look for bean fields with this specified minimum visibility. */ public final Visibility getBeanFieldVisibility() { return beanFieldVisibility; } /** * BeanMap.put() returns old property value. * * @see BeanContext.Builder#beanMapPutReturnsOldValue() * @return * true if the {@link BeanMap#put(String,Object) BeanMap.put()} method will return old property values. *
Otherwise, it returns null. */ public final boolean isBeanMapPutReturnsOldValue() { return beanMapPutReturnsOldValue; } /** * Minimum bean method visibility. * * @see BeanContext.Builder#beanMethodVisibility(Visibility) * @return * Only look for bean methods with this specified minimum visibility. */ public final Visibility getBeanMethodVisibility() { return beanMethodVisibility; } /** * Beans require no-arg constructors. * * @see BeanContext.Builder#beansRequireDefaultConstructor() * @return * true if 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. */ public final boolean isBeansRequireDefaultConstructor() { return beansRequireDefaultConstructor; } /** * Beans require Serializable interface. * * @see BeanContext.Builder#beansRequireSerializable() * @return * true if 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. */ public final boolean isBeansRequireSerializable() { return beansRequireSerializable; } /** * Beans require setters for getters. * * @see BeanContext.Builder#beansRequireSettersForGetters() * @return * true if only getters that have equivalent setters will be considered as properties on a bean. *
Otherwise, they are ignored. */ public final boolean isBeansRequireSettersForGetters() { return beansRequireSettersForGetters; } /** * Beans require at least one property. * * @see BeanContext.Builder#disableBeansRequireSomeProperties() * @return * true if a Java class doesn't need to contain at least 1 property to be considered a bean. *
Otherwise, the bean is serialized as a string using the {@link Object#toString()} method. */ public final boolean isBeansRequireSomeProperties() { return beansRequireSomeProperties; } /** * Bean type property name. * * @see BeanContext.Builder#typePropertyName(String) * @return * 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. */ public final String getBeanTypePropertyName() { return typePropertyName; } /** * Find fluent setters. * *

Description:
*

* * @see BeanContext.Builder#findFluentSetters() * @return * true if fluent setters are detected on beans. */ public final boolean isFindFluentSetters() { return findFluentSetters; } /** * Ignore invocation errors on getters. * * @see BeanContext.Builder#ignoreInvocationExceptionsOnGetters() * @return * true if errors thrown when calling bean getter methods are silently ignored. */ public final boolean isIgnoreInvocationExceptionsOnGetters() { return ignoreInvocationExceptionsOnGetters; } /** * Ignore invocation errors on setters. * * @see BeanContext.Builder#ignoreInvocationExceptionsOnSetters() * @return * true if errors thrown when calling bean setter methods are silently ignored. */ public final boolean isIgnoreInvocationExceptionsOnSetters() { return ignoreInvocationExceptionsOnSetters; } /** * Silently ignore missing setters. * * @see BeanContext.Builder#disableIgnoreMissingSetters() * @return * true if trying to set a value on a bean property without a setter should throw a {@link BeanRuntimeException}. */ public final boolean isIgnoreMissingSetters() { return ignoreMissingSetters; } /** * Ignore transient fields. * * @see BeanContext.Builder#disableIgnoreTransientFields() * @return * true if fields and methods marked as transient should not be ignored. */ protected final boolean isIgnoreTransientFields() { return ignoreTransientFields; } /** * Ignore unknown properties. * * @see BeanContext.Builder#ignoreUnknownBeanProperties() * @return * true if trying to set a value on a non-existent bean property is silently ignored. *
Otherwise, a {@code RuntimeException} is thrown. */ public final boolean isIgnoreUnknownBeanProperties() { return ignoreUnknownBeanProperties; } /** * Ignore unknown enum values. * * @see BeanContext.Builder#ignoreUnknownEnumValues() * @return * true if unknown enum values should be set as null instead of throwing an exception. */ public final boolean isIgnoreUnknownEnumValues() { return ignoreUnknownEnumValues; } /** * Ignore unknown properties with null values. * * @see BeanContext.Builder#disableIgnoreUnknownNullBeanProperties() * @return * true if trying to set a null value on a non-existent bean property should throw a {@link BeanRuntimeException}. */ public final boolean isIgnoreUnknownNullBeanProperties() { return ignoreUnknownNullBeanProperties; } /** * Bean class exclusions. * * @see BeanContext.Builder#notBeanClasses(Class...) * @return * The list of classes that are explicitly not beans. */ protected final Class[] getNotBeanClasses() { return notBeanClassesArray; } /** * Bean package exclusions. * * @see BeanContext.Builder#notBeanPackages(String...) * @return * The list of fully-qualified package names to exclude from being classified as beans. */ public final String[] getNotBeanPackagesNames() { return notBeanPackageNames; } /** * Bean package exclusions. * * @see BeanContext.Builder#notBeanPackages(String...) * @return * The list of package name prefixes to exclude from being classified as beans. */ protected final String[] getNotBeanPackagesPrefixes() { return notBeanPackagePrefixes; } /** * Java object swaps. * * @see BeanContext.Builder#swaps(Class...) * @return * The list POJO swaps defined. */ public final ObjectSwap[] getSwaps() { return swapArray; } /** * Bean property namer. * * @see BeanContext.Builder#propertyNamer(Class) * @return * The interface used to calculate bean property names. */ public final PropertyNamer getPropertyNamer() { return propertyNamerBean; } /** * Sort bean properties. * * @see BeanContext.Builder#sortProperties() * @return * true if all bean properties will be serialized and access in alphabetical order. */ public final boolean isSortProperties() { return sortProperties; } /** * Use enum names. * * @see BeanContext.Builder#useEnumNames() * @return * true if enums are always serialized by name, not using {@link Object#toString()}. */ public final boolean isUseEnumNames() { return useEnumNames; } /** * Use interface proxies. * * @see BeanContext.Builder#disableInterfaceProxies() * @return * true if interfaces will be instantiated as proxy classes through the use of an * {@link InvocationHandler} if there is no other way of instantiating them. */ public final boolean isUseInterfaceProxies() { return useInterfaceProxies; } /** * Use Java Introspector. * * @see BeanContext.Builder#useJavaBeanIntrospector() * @return * true if the built-in Java bean introspector should be used for bean introspection. */ public final boolean isUseJavaBeanIntrospector() { return useJavaBeanIntrospector; } /** * Locale. * * @see BeanContext.Builder#locale(Locale) * @return * The default locale for serializer and parser sessions. */ public final Locale getDefaultLocale() { return locale; } /** * Media type. * * @see BeanContext.Builder#mediaType(MediaType) * @return * The default media type value for serializer and parser sessions. */ public final MediaType getDefaultMediaType() { return mediaType; } /** * Time zone. * * @see BeanContext.Builder#timeZone(TimeZone) * @return * The default timezone for serializer and parser sessions. */ public final TimeZone getDefaultTimeZone() { return timeZone; } /** * Returns the serializer to use for serializing beans when using the {@link BeanSession#convertToType(Object, Class)} * and related methods. * * @return The serializer. May be null if all initialization has occurred. */ protected WriterSerializer getBeanToStringSerializer() { if (beanToStringSerializer == null) { if (JsonSerializer.DEFAULT == null) return null; this.beanToStringSerializer = JsonSerializer.create().beanContext(this).sq().simpleAttrs().build(); } return beanToStringSerializer; } //----------------------------------------------------------------------------------------------------------------- // Other methods //----------------------------------------------------------------------------------------------------------------- @Override /* Context */ protected JsonMap properties() { return filteredMap() .append("id", System.identityHashCode(this)) .append("beanClassVisibility", beanClassVisibility) .append("beanConstructorVisibility", beanConstructorVisibility) .append("beanDictionary", beanDictionary) .append("beanFieldVisibility", beanFieldVisibility) .append("beanMethodVisibility", beanMethodVisibility) .append("beansRequireDefaultConstructor", beansRequireDefaultConstructor) .append("beansRequireSerializable", beansRequireSerializable) .append("beansRequireSettersForGetters", beansRequireSettersForGetters) .append("beansRequireSomeProperties", beansRequireSomeProperties) .append("ignoreTransientFields", ignoreTransientFields) .append("ignoreInvocationExceptionsOnGetters", ignoreInvocationExceptionsOnGetters) .append("ignoreInvocationExceptionsOnSetters", ignoreInvocationExceptionsOnSetters) .append("ignoreUnknownBeanProperties", ignoreUnknownBeanProperties) .append("ignoreUnknownNullBeanProperties", ignoreUnknownNullBeanProperties) .append("notBeanClasses", notBeanClasses) .append("notBeanPackageNames", notBeanPackageNames) .append("notBeanPackagePrefixes", notBeanPackagePrefixes) .append("swaps", swaps) .append("sortProperties", sortProperties) .append("useEnumNames", useEnumNames) .append("useInterfaceProxies", useInterfaceProxies) .append("useJavaBeanIntrospector", useJavaBeanIntrospector); } }