![JAR search and dependency download from the Maven repository](/logo.png)
com.oracle.coherence.io.json.genson.GensonBuilder Maven / Gradle / Ivy
/*
* Copyright (c) 2020, 2022, Oracle and/or its affiliates.
*
* Copyright 2011-2014 Genson - Cepoi Eugen
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use
* this file except in compliance with the License.
*
* 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 com.oracle.coherence.io.json.genson;
import com.oracle.coherence.io.json.genson.convert.BasicConvertersFactory;
import com.oracle.coherence.io.json.genson.convert.BeanViewConverter;
import com.oracle.coherence.io.json.genson.convert.ChainedFactory;
import com.oracle.coherence.io.json.genson.convert.CircularClassReferenceConverterFactory;
import com.oracle.coherence.io.json.genson.convert.ClassMetadataConverter;
import com.oracle.coherence.io.json.genson.convert.ContextualFactory;
import com.oracle.coherence.io.json.genson.convert.DefaultConverters;
import com.oracle.coherence.io.json.genson.convert.NullConverterFactory;
import com.oracle.coherence.io.json.genson.convert.RuntimeTypeConverter;
import com.oracle.coherence.io.json.genson.ext.GensonBundle;
import com.oracle.coherence.io.json.genson.reflect.ASMCreatorParameterNameResolver;
import com.oracle.coherence.io.json.genson.reflect.AbstractBeanDescriptorProvider;
import com.oracle.coherence.io.json.genson.reflect.AbstractBeanDescriptorProvider.ContextualConverterFactory;
import com.oracle.coherence.io.json.genson.reflect.AbstractBeanDescriptorProvider.ContextualFactoryDecorator;
import com.oracle.coherence.io.json.genson.reflect.BaseBeanDescriptorProvider;
import com.oracle.coherence.io.json.genson.reflect.BeanDescriptorProvider;
import com.oracle.coherence.io.json.genson.reflect.BeanDescriptorProvider.CompositeBeanDescriptorProvider;
import com.oracle.coherence.io.json.genson.reflect.BeanMutatorAccessorResolver;
import com.oracle.coherence.io.json.genson.reflect.BeanPropertyFactory;
import com.oracle.coherence.io.json.genson.reflect.BeanViewDescriptorProvider;
import com.oracle.coherence.io.json.genson.reflect.DefaultTypes;
import com.oracle.coherence.io.json.genson.reflect.PropertyFilter;
import com.oracle.coherence.io.json.genson.reflect.PropertyNameResolver;
import com.oracle.coherence.io.json.genson.reflect.RenamingPropertyNameResolver;
import com.oracle.coherence.io.json.genson.reflect.RuntimePropertyFilter;
import com.oracle.coherence.io.json.genson.reflect.TypeUtil;
import com.oracle.coherence.io.json.genson.reflect.UnknownPropertyHandler;
import com.oracle.coherence.io.json.genson.reflect.VisibilityFilter;
import com.oracle.coherence.io.json.genson.stream.ValueType;
import java.lang.reflect.Type;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Use the GensonBuilder class when you want to create a custom Genson instance. This class allows you
* for example to register custom converters/serializers/deserializers
* {@link #withConverters(Converter...)} or custom converter Factories
* {@link #withConverterFactory(Factory)}.
*
* This class combines the GensonBuilder design pattern with template pattern providing handy
* configuration and extensibility. All its public methods are intended to be used in the
* GensonBuilder "style" and its protected methods are part of the template. When you call
* {@link #create()} method, it will start assembling all the configuration and build all the
* required components by using the protected methods. For example if you wish to use in your
* projects a GensonBuilder that will always create some custom
* {@link com.oracle.coherence.io.json.genson.reflect.BeanDescriptorProvider BeanDescriptorProvider} you have to
* extend {@link #createBeanDescriptorProvider()}, or imagine that you implemented some
* Converters that you always want to register then override {@link #getDefaultConverters()}.
*
* @author Eugen Cepoi
*/
public class GensonBuilder {
private final DefaultTypes defaultTypes = new DefaultTypes();
private final Map> serializersMap = new HashMap<>();
private final Map> deserializersMap = new HashMap<>();
private final List> converterFactories = new ArrayList<>();
private final List> contextualFactories = new ArrayList<>();
private final List beanPropertyFactories = new ArrayList<>();
private boolean skipNull = false;
private boolean htmlSafe = false;
private boolean withClassMetadata = false;
private boolean throwExcOnNoDebugInfo = false;
private boolean useGettersAndSetters = true;
private boolean useFields = true;
private boolean withBeanViewConverter = false;
private boolean useRuntimeTypeForSerialization = false;
private boolean withDebugInfoPropertyNameResolver = false;
private boolean strictDoubleParse = false;
private boolean indent = false;
private boolean metadata = false;
private boolean failOnMissingProperty = false;
private boolean enforceTypeAliases = false;
private List _bundles = new ArrayList();
private PropertyNameResolver propertyNameResolver;
private List propertyNameResolvers = new ArrayList<>();
private List renamingResolvers = new ArrayList<>();
private BeanMutatorAccessorResolver mutatorAccessorResolver;
private List mutatorAccessorResolvers = new ArrayList<>();
private List propertyFilters = new ArrayList<>();
private VisibilityFilter propertyFilter = VisibilityFilter.PACKAGE_PUBLIC;
private VisibilityFilter methodFilter = VisibilityFilter.PACKAGE_PUBLIC;
private VisibilityFilter constructorFilter = VisibilityFilter.PACKAGE_PUBLIC;
private ClassLoader classLoader = getClass().getClassLoader();
private BeanDescriptorProvider beanDescriptorProvider;
private DateFormat dateFormat = SimpleDateFormat.getDateTimeInstance();
private boolean useDateAsTimestamp = true;
private boolean classMetadataWithStaticType = true;
// for the moment we don't allow to override
private BeanViewDescriptorProvider beanViewDescriptorProvider;
private final Map> withClassAliases = new HashMap<>();
private final Map compatibilityAliases = new HashMap<>();
private final Map withPackageAliases = new HashMap<>();
private final Map, BeanView>> registeredViews = new HashMap, BeanView>>();
private ChainedFactory customFactoryChain;
private Modifier chainedFactoryModifier;
private final Map, Object> defaultValues = new HashMap, Object>();
private boolean failOnNullPrimitive = false;
private RuntimePropertyFilter runtimePropertyFilter = RuntimePropertyFilter.noFilter;
private UnknownPropertyHandler unknownPropertyHandler;
public GensonBuilder() {
defaultValues.put(int.class, 0);
defaultValues.put(long.class, 0l);
defaultValues.put(short.class, (short) 0);
defaultValues.put(double.class, 0d);
defaultValues.put(float.class, 0f);
defaultValues.put(boolean.class, false);
defaultValues.put(byte.class, (byte) 0);
defaultValues.put(char.class, '\u0000');
}
/**
* Set the class to use for deserialization of the specified
* {@link ValueType} when the Java type cannot be determined
* based on static type information or JSON metadata.
*
* @param type the {@code ValueType} to set the default class for
* @param clazz the default class for the specified {@code ValueType}
*
* @return a reference to this builder
*/
public GensonBuilder setDefaultType(ValueType type, Class> clazz) {
defaultTypes.setClass(type, clazz);
return this;
}
/**
* Alias used in serialized class metadata instead of the full class name. See
* {@link com.oracle.coherence.io.json.genson.convert.ClassMetadataConverter ClassMetadataConverter} for more
* metadata. If you add an alias, it will automatically enable the class metadata feature,
* as if you used {@link #useClassMetadata(boolean)}.
*
* @param alias
* @param forClass
* @return a reference to this builder.
* @throws IllegalArgumentException if the specified alias has already been defined
*/
public GensonBuilder addAlias(String alias, Class> forClass) {
if (withClassAliases.containsKey(alias)) {
throw new IllegalArgumentException(
String.format("Alias %s already defined for type %s", alias, withClassAliases.get(alias).getName()));
}
withClassMetadata = true;
withClassAliases.put(alias, forClass);
return this;
}
/**
* Allows for adding aliases to aliases to allow backwards compat in alias changes.
*
* @param alias the alias
* @param aliasFor the alias {@code alias} references
*
* @throws IllegalArgumentException if the provided alias is already defined.
* @return a reference to this builder
*/
public GensonBuilder addCompatibilityAlias(String alias, String aliasFor) {
if (compatibilityAliases.containsKey(alias)) {
throw new IllegalArgumentException(
String.format("Alias %s already defined for alias %s", alias, compatibilityAliases.get(alias)));
}
withClassMetadata = true;
compatibilityAliases.put(alias, aliasFor);
return this;
}
/**
* Similar to {@link #addAlias(String, Class)}, this allows creating an alias for all
* serialized classes within a package. When a class is present within the specified
* package, instead of the full class name being serialized, it will generate the
* following String:
* alias + '.' + className
*
* @param alias alias for classes within a specific package.
* @param forPackage the package to which the alias will be applied
*
* @throws IllegalArgumentException if the specified alias has already been defined
*
* @return a reference to this builder
*
* @since 2.0
*
* @see #addAlias(String, Class)
*/
public GensonBuilder addPackageAlias(String alias, String forPackage) {
if (withPackageAliases.containsKey(alias)) {
throw new IllegalArgumentException(
String.format("Alias %s already defined for package %s", alias, withPackageAliases.get(alias)));
}
withClassMetadata = true;
withPackageAliases.put(alias, forPackage);
return this;
}
/**
* Registers converters mapping them to their corresponding parameterized type.
*
* @param converter
* @return a reference to this builder.
*/
public GensonBuilder withConverters(Converter>... converter) {
for (Converter> c : converter) {
Type typeOfConverter = TypeUtil.typeOf(0,
TypeUtil.lookupGenericType(Converter.class, c.getClass()));
typeOfConverter = TypeUtil.expandType(typeOfConverter, c.getClass());
registerConverter(c, typeOfConverter);
}
return this;
}
/**
* Register converter by mapping it to type argument.
*
* @param converter to register
* @param type of objects this converter handles
* @return a reference to this builder.
*/
public GensonBuilder withConverter(Converter converter, Class extends T> type) {
registerConverter(converter, type);
return this;
}
/**
* Register converter by mapping it to the parameterized type of type argument.
*
* @param converter to register
* @param type of objects this converter handles
* @return a reference to this builder.
*/
public GensonBuilder withConverter(Converter converter, GenericType extends T> type) {
registerConverter(converter, type.getType());
return this;
}
private void registerConverter(Converter converter, Type type) {
if (serializersMap.containsKey(type))
throw new IllegalStateException("Can not register converter "
+ converter.getClass()
+ ". A custom serializer is already registered for type " + type);
if (deserializersMap.containsKey(type))
throw new IllegalStateException("Can not register converter "
+ converter.getClass()
+ ". A custom deserializer is already registered for type " + type);
serializersMap.put(type, converter);
deserializersMap.put(type, converter);
}
public GensonBuilder withSerializers(Serializer>... serializer) {
for (Serializer> s : serializer) {
Type typeOfConverter = TypeUtil.typeOf(0,
TypeUtil.lookupGenericType(Serializer.class, s.getClass()));
typeOfConverter = TypeUtil.expandType(typeOfConverter, s.getClass());
registerSerializer(s, typeOfConverter);
}
return this;
}
public GensonBuilder withSerializer(Serializer serializer, Class extends T> type) {
registerSerializer(serializer, type);
return this;
}
public GensonBuilder withSerializer(Serializer serializer, GenericType extends T> type) {
registerSerializer(serializer, type.getType());
return this;
}
private void registerSerializer(Serializer serializer, Type type) {
if (serializersMap.containsKey(type))
throw new IllegalStateException("Can not register serializer "
+ serializer.getClass()
+ ". A custom serializer is already registered for type " + type);
serializersMap.put(type, serializer);
}
public GensonBuilder withDeserializers(Deserializer>... deserializer) {
for (Deserializer> d : deserializer) {
Type typeOfConverter = TypeUtil.typeOf(0,
TypeUtil.lookupGenericType(Deserializer.class, d.getClass()));
typeOfConverter = TypeUtil.expandType(typeOfConverter, d.getClass());
registerDeserializer(d, typeOfConverter);
}
return this;
}
public GensonBuilder withDeserializer(Deserializer deserializer, Class extends T> type) {
registerDeserializer(deserializer, type);
return this;
}
public GensonBuilder withDeserializer(Deserializer deserializer,
GenericType extends T> type) {
registerDeserializer(deserializer, type.getType());
return this;
}
private void registerDeserializer(Deserializer deserializer, Type type) {
if (deserializersMap.containsKey(type))
throw new IllegalStateException("Can not register deserializer "
+ deserializer.getClass()
+ ". A custom deserializer is already registered for type " + type);
deserializersMap.put(type, deserializer);
}
/**
* Registers converter factories.
*
* @param factory to register
* @return a reference to this builder.
*/
public GensonBuilder withConverterFactory(Factory extends Converter>> factory) {
converterFactories.add(factory);
return this;
}
/**
* Registers serializer factories.
*
* @param factory to register
* @return a reference to this builder.
*/
public GensonBuilder withSerializerFactory(Factory extends Serializer>> factory) {
converterFactories.add(factory);
return this;
}
/**
* Registers deserializer factories.
*
* @param factory to register
* @return a reference to this builder.
*/
public GensonBuilder withDeserializerFactory(Factory extends Deserializer>> factory) {
converterFactories.add(factory);
return this;
}
/**
* ContextualFactory is actually in a beta status, it will not be removed, but might be
* refactored.
*/
public GensonBuilder withContextualFactory(ContextualFactory>... factories) {
contextualFactories.addAll(Arrays.asList(factories));
return this;
}
/**
* A ChainedFactory provides a way to use custom Converters that have access to the default Converters.
* An example of use is to wrap incoming/outgoing json in a root object and delegate then the ser/de to the default
* Converter.
*
* This mechanism is internally used by Genson to decorate the different Converters with additional behaviour
* (null handling, ser/de of polymorphic types with class info, runtime type based ser/de, etc).
*
* Note that you can't use it in situations where you want to start reading/writing some partial infos and want to
* delegate the rest to the default Converter.
*/
public GensonBuilder withConverterFactory(ChainedFactory chainedFactory) {
if (customFactoryChain == null) customFactoryChain = chainedFactory;
else {
customFactoryChain.append(chainedFactory);
}
return this;
}
public GensonBuilder withConverterFactory(Modifier modifier) {
chainedFactoryModifier = modifier;
return this;
}
/**
* Allows you to register new BeanPropertyFactory responsible of creating BeanProperty
* accessors, mutators and BeanCreators. This is a very low level feature, you probably
* don't need it.
*/
public GensonBuilder withBeanPropertyFactory(BeanPropertyFactory... factories) {
beanPropertyFactories.addAll(Arrays.asList(factories));
return this;
}
/**
* Register some genson bundles. For example to enable JAXB support:
*
*
* builder.withBundle(new JAXBExtension());
*
*
* All bundles should be registered before any other customization.
*
* @see GensonBundle
*/
public GensonBuilder withBundle(GensonBundle... bundles) {
for (GensonBundle bundle : bundles) {
bundle.configure(this);
_bundles.add(bundle);
}
return this;
}
/**
* Override the default classloader
*
* @param loader classloader which will be used to load classes while deserializing
* @return a reference to this builder
*/
public GensonBuilder withClassLoader(ClassLoader loader) {
classLoader = loader;
return this;
}
/**
* Replaces default {@link com.oracle.coherence.io.json.genson.reflect.BeanMutatorAccessorResolver
* BeanMutatorAccessorResolver} by the specified one.
*
* @param resolver
* @return a reference to this builder.
*/
public GensonBuilder set(BeanMutatorAccessorResolver resolver) {
mutatorAccessorResolver = resolver;
return this;
}
/**
* Replaces default {@link com.oracle.coherence.io.json.genson.reflect.PropertyNameResolver
* PropertyNameResolver} by the specified one.
*
* @param resolver
* @return a reference to this builder.
*/
public GensonBuilder set(PropertyNameResolver resolver) {
propertyNameResolver = resolver;
return this;
}
/**
* Register additional BeanMutatorAccessorResolver that will be used before the standard
* ones.
*
* @param resolvers
* @return a reference to this builder.
*/
public GensonBuilder with(BeanMutatorAccessorResolver... resolvers) {
mutatorAccessorResolvers.addAll(Arrays.asList(resolvers));
return this;
}
public Map> getSerializersMap() {
return Collections.unmodifiableMap(serializersMap);
}
public Map> getDeserializersMap() {
return Collections.unmodifiableMap(deserializersMap);
}
public ClassLoader getClassLoader() {
return classLoader;
}
/**
* Registers the specified resolvers in the order they were defined and before the standard
* ones.
*
* @param resolvers
* @return a reference to this builder.
*/
public GensonBuilder with(PropertyNameResolver... resolvers) {
propertyNameResolvers.addAll(Arrays.asList(resolvers));
return this;
}
/**
* Renames all fields named field to toName.
*/
public GensonBuilder rename(String field, String toName) {
return rename(field, null, toName, null);
}
/**
* Renames all fields of type fieldOfType to toName.
*/
public GensonBuilder rename(Class> fieldOfType, String toName) {
return rename(null, null, toName, fieldOfType);
}
/**
* Renames all fields named field declared in class fromClass to toName.
*/
public GensonBuilder rename(String field, Class> fromClass, String toName) {
return rename(field, fromClass, toName, null);
}
/**
* Renames all fields named field and of type fieldOfType to toName.
*/
public GensonBuilder rename(String field, String toName, Class> fieldOfType) {
return rename(field, null, toName, fieldOfType);
}
/**
* Renames all fields named field, of type fieldOfType and declared in fromClass to toName.
*/
public GensonBuilder rename(final String field, final Class> fromClass, final String toName,
final Class> ofType) {
renamingResolvers.add(new RenamingPropertyNameResolver(field, fromClass, ofType, toName));
return this;
}
public GensonBuilder exclude(String field) {
return filter(field, null, null, true);
}
public GensonBuilder exclude(Class> fieldOfType) {
return filter(null, null, fieldOfType, true);
}
public GensonBuilder exclude(String field, Class> fromClass) {
return filter(field, fromClass, null, true);
}
public GensonBuilder exclude(String field, Class> fromClass, Class> ofType) {
return filter(field, fromClass, ofType, true);
}
public GensonBuilder include(String field) {
return filter(field, null, null, false);
}
public GensonBuilder include(Class> fieldOfType) {
return filter(null, null, fieldOfType, false);
}
public GensonBuilder include(BeanMutatorAccessorResolver resolver) {
propertyFilters.add(0, resolver);
return this;
}
public GensonBuilder include(String field, Class> fromClass) {
return filter(field, fromClass, null, false);
}
public GensonBuilder include(String field, Class> fromClass, Class> ofType) {
return filter(field, fromClass, ofType, false);
}
private GensonBuilder filter(final String field, final Class> declaringClass,
final Class> ofType, final boolean exclude) {
if (exclude) {
propertyFilters.add(new PropertyFilter(exclude, field, declaringClass, ofType));
}
else {
propertyFilters.add(0, new PropertyFilter(exclude, field, declaringClass, ofType));
}
return this;
}
/**
* If true will not serialize null values
*
* @param skipNull indicates whether null values should be serialized or not.
* @return a reference to this builder.
*/
public GensonBuilder setSkipNull(boolean skipNull) {
this.skipNull = skipNull;
return this;
}
public boolean isSkipNull() {
return skipNull;
}
/**
* If true \,<,>,&,= characters will be replaced by \u0027, \u003c, \u003e, \u0026, \u003d
*
* @param htmlSafe indicates whether serialized data should be html safe.
* @return a reference to this builder.
*/
public GensonBuilder setHtmlSafe(boolean htmlSafe) {
this.htmlSafe = htmlSafe;
return this;
}
public boolean isHtmlSafe() {
return htmlSafe;
}
/**
* Indicates whether class metadata should be serialized and used during deserialization.
*
* @see com.oracle.coherence.io.json.genson.convert.ClassMetadataConverter ClassMetadataConverter
*/
public GensonBuilder useClassMetadata(boolean enabled) {
this.withClassMetadata = enabled;
this.metadata = true;
return this;
}
/**
* Specifies the data format that should be used for java.util.Date serialization and
* deserialization.
*
* @param dateFormat
* @return a reference to this builder.
*/
public GensonBuilder useDateFormat(DateFormat dateFormat) {
this.dateFormat = dateFormat;
return this;
}
/**
* @return {@code true} if type aliasing is enforced, i.e., any class metadata that is not referenced
* as a type or package alias will result in an error being raised during ser/deser operations.
*/
public boolean isEnforceTypeAliases() {
return enforceTypeAliases;
}
/**
* Enables enforcement that all class metadata must be defined by aliases instead of raw types. Any raw types
* discovered during ser/deser operations will result in an error being thrown.
*
* @param enforceTypeAliases enable or disable type alias enforcement
* @return this
*/
public GensonBuilder setEnforceTypeAliases(boolean enforceTypeAliases) {
this.enforceTypeAliases = enforceTypeAliases;
return this;
}
public boolean isThrowExceptionOnNoDebugInfo() {
return throwExcOnNoDebugInfo;
}
/**
* Used in conjunction with {@link #useConstructorWithArguments(boolean)}. If true
* an exception will be thrown when a class has been compiled without debug informations.
*
* @param throwExcOnNoDebugInfo
* @return a reference to this builder.
* @see com.oracle.coherence.io.json.genson.reflect.ASMCreatorParameterNameResolver
* ASMCreatorParameterNameResolver
*/
public GensonBuilder setThrowExceptionIfNoDebugInfo(boolean throwExcOnNoDebugInfo) {
this.throwExcOnNoDebugInfo = throwExcOnNoDebugInfo;
return this;
}
/**
* If true, getters and setters would be used during serialization/deserialization in favor
* of fields. If there is not getter/setter for a field then the field will be used, except
* if you specified that fields should not be used with {@link #useFields(boolean)}. By
* default getters, setters and fields will be used.
*/
public GensonBuilder useMethods(boolean enabled) {
this.useGettersAndSetters = enabled;
return this;
}
public GensonBuilder useMethods(boolean enabled, VisibilityFilter visibility) {
useMethods(enabled);
return setMethodFilter(visibility);
}
/**
* If true, fields will be used when no getter/setter is available, except if you specified
* that no getter/setter should be used with {@link #useMethods(boolean)}, in
* that case only fields will be used. By default getters, setters and fields will be used.
*/
public GensonBuilder useFields(boolean enabled) {
this.useFields = enabled;
return this;
}
public GensonBuilder useFields(boolean enabled, VisibilityFilter visibility) {
useFields(enabled);
return setFieldFilter(visibility);
}
/**
* If true {@link BeanView} mechanism will be enabled.
*/
public GensonBuilder useBeanViews(boolean enabled) {
this.withBeanViewConverter = enabled;
return this;
}
/**
* If true the concrete type of the serialized object will always be used. So if you have
* List type it will not use the Number serializer but the one for the concrete type
* of the current value.
*
* @param enabled
* @return a reference to this builder.
*/
public GensonBuilder useRuntimeType(boolean enabled) {
this.useRuntimeTypeForSerialization = enabled;
return this;
}
/**
* If true constructor and method arguments name will be resolved from the generated debug
* symbols during compilation. It is a very powerful feature from Genson, you should have a
* look at {@link com.oracle.coherence.io.json.genson.reflect.ASMCreatorParameterNameResolver
* ASMCreatorParameterNameResolver}.
*
* @param enabled
* @return a reference to this builder.
* @see #setThrowExceptionIfNoDebugInfo(boolean)
*/
public GensonBuilder useConstructorWithArguments(boolean enabled) {
this.withDebugInfoPropertyNameResolver = enabled;
return this;
}
public GensonBuilder setFieldFilter(VisibilityFilter propertyFilter) {
this.propertyFilter = propertyFilter;
return this;
}
public GensonBuilder setMethodFilter(VisibilityFilter methodFilter) {
this.methodFilter = methodFilter;
return this;
}
public GensonBuilder setConstructorFilter(VisibilityFilter constructorFilter) {
this.constructorFilter = constructorFilter;
return this;
}
public GensonBuilder useStrictDoubleParse(boolean strictDoubleParse) {
this.strictDoubleParse = strictDoubleParse;
return this;
}
/**
* If true outputed json will be indented using two spaces, otherwise (by default) all is
* printed on same line.
*/
public GensonBuilder useIndentation(boolean indent) {
this.indent = indent;
return this;
}
public GensonBuilder useDateAsTimestamp(boolean enabled) {
this.useDateAsTimestamp = enabled;
return this;
}
public GensonBuilder useMetadata(boolean metadata) {
this.metadata = metadata;
return this;
}
public GensonBuilder useByteAsInt(boolean enable) {
if (enable) {
withConverters(DefaultConverters.ByteArrayAsIntArrayConverter.instance);
}
return this;
}
/**
* If set to true, Genson will throw a JsonBindingException when it encounters a property in the incoming json that does not match
* a property in the class.
* False by default.
* @param enable
* @return
*/
public GensonBuilder failOnMissingProperty(boolean enable) {
this.failOnMissingProperty = enable;
return this;
}
/**
* If set to false, during serialization class metadata will be serialized only for types where the runtime type differs from the static one.
* Ex:
*
*
* class Person {
* public Address address;
* }
*
*
* Here if the concrete instance of address is Address then this type will not be serialized as metadata, but if they differ then
* it is serialized. By default this option is true, all types are serialized.
* @param enable
* @return
*/
public GensonBuilder useClassMetadataWithStaticType(boolean enable) {
this.classMetadataWithStaticType = enable;
return this;
}
/**
* Wrap a single value into a list when a list is expected. Useful when dealing with APIs that unwrap
* arrays containing a single value. Disabled by default.
*/
public GensonBuilder acceptSingleValueAsList(boolean enable) {
if (enable) withConverterFactory(DefaultConverters.SingleValueAsListFactory.instance);
return this;
}
/**
* Uses the passed value as the default value for this type.
*/
public GensonBuilder useDefaultValue(Object value, Class> targetType) {
defaultValues.put(targetType, value);
return this;
}
/**
* Will wrap all the root objects under outputKey during serializaiton and unwrap the content under
* inputKey during deserializaiton. For example:
*
*
* Genson genson = new GensonBuilder().wrapRootValues("request", "response").create();
*
* // would produce: {"response": {... person properties ...}}
* genson.serialize(person);
*
* Person p = genson.deserialize("{\"request\":{...}}", Person.class);
*
*
* If you need this mechanism only for some types or using different root keys, then you can register JaxbBundle with
* wrapRootValues(true) and annotate the specific classes with XmlRootElement.
*/
public GensonBuilder wrapRootValues(final String inputKey, final String outputKey) {
return withConverterFactory(new ChainedFactory() {
@Override
protected Converter> create(Type type, Genson genson, Converter> nextConverter) {
return new DefaultConverters.WrappedRootValueConverter
© 2015 - 2025 Weber Informatics LLC | Privacy Policy