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

dk.cloudcreate.essentials.jackson.immutable.EssentialsImmutableJacksonModule Maven / Gradle / Ivy

Go to download

This library focuses purely on providing https://github.com/FasterXML/jackson deserialization support for deserializing immutable objects

The newest version!
/*
 * Copyright 2021-2024 the original author or authors.
 *
 * Licensed 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
 *
 *      https://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 dk.cloudcreate.essentials.jackson.immutable;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.databind.Module;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.deser.*;
import com.fasterxml.jackson.databind.introspect.VisibilityChecker;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import dk.cloudcreate.essentials.shared.FailFast;
import org.objenesis.Objenesis;

/**
 * The Jackson module that assists Jackson support for deserializing immutable classes or other classes that don't have a suitable creator (constructor, or no-arg static factory method, etc.).
*
* This is very useful for when you're using Record's (in Java 14+) or other types supporting immutable objects, as it allows Jackson to create an object instance * without requiring a matching constructing.
* Property/Field values are set directly using reflection, even if the fields themselves are final.
*
* For this to work we require that opinionated defaults, such as using FIELDS for serialization, have been applied to the {@link ObjectMapper} instance.
* This can e.g. be accomplished by using the {@link EssentialsImmutableJacksonModule#createObjectMapper(Module...)} method *

* The object creation/instantiation logic is as follows:
*

    *
  • First it will try using the standard Jackson {@link ValueInstantiator}
  • *
  • IF the standard Jackson {@link ValueInstantiator} cannot create a new instance of the Class, then we will use {@link Objenesis} to create an instance of the Class
    * BE AWARE: If the object is created/instantiated using {@link Objenesis} then NO constructor will be called and NO fields will have their default values set by Java!!!! *
  • *
*/ public final class EssentialsImmutableJacksonModule extends SimpleModule { /** * Configure the Jackson Module */ public EssentialsImmutableJacksonModule() { super("Essentials-Immutable"); } @Override public void setupModule(SetupContext context) { context.addBeanDeserializerModifier(new BeanDeserializerModifier() { @Override public BeanDeserializerBuilder updateBuilder(DeserializationConfig config, BeanDescription beanDesc, BeanDeserializerBuilder builder) { builder.setValueInstantiator(new ImmutableObjectsValueInstantiator(beanDesc.getBeanClass(), builder.getValueInstantiator())); return builder; } }); super.setupModule(context); } /** * Convenience method for creating a new {@link ObjectMapper} with our {@link EssentialsImmutableJacksonModule} added and with opinionated defaults like explicit JSON mapping, * not failing on unknown properties or empty beans, propagation of transient markers, using FIELDS for serialization (i.e. disabling auto detection of getters * and setters and instead using field and allowing ANY visibility for fields and constructors and none for getters/setters) * * @param additionalModules Additional modules that should be added to the {@link ObjectMapper} instance created * @return new {@link ObjectMapper} instance configured with sensible defaults and the {@link EssentialsImmutableJacksonModule} added */ public static ObjectMapper createObjectMapper(Module... additionalModules) { FailFast.requireNonNull(additionalModules, "additionalModules is null"); return JsonMapper.builder() .visibility(VisibilityChecker.Std.Std.defaultInstance() .withGetterVisibility(JsonAutoDetect.Visibility.NONE) .withSetterVisibility(JsonAutoDetect.Visibility.NONE) .withFieldVisibility(JsonAutoDetect.Visibility.ANY) .withCreatorVisibility(JsonAutoDetect.Visibility.ANY)) .disable(MapperFeature.AUTO_DETECT_GETTERS) .disable(MapperFeature.AUTO_DETECT_IS_GETTERS) .disable(MapperFeature.AUTO_DETECT_SETTERS) .disable(MapperFeature.DEFAULT_VIEW_INCLUSION) .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) .disable(SerializationFeature.FAIL_ON_EMPTY_BEANS) .enable(MapperFeature.AUTO_DETECT_CREATORS) .enable(MapperFeature.AUTO_DETECT_FIELDS) .enable(MapperFeature.PROPAGATE_TRANSIENT_MARKER) .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) .addModule(new EssentialsImmutableJacksonModule()) .addModules(additionalModules) .build(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy