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

io.github.honhimw.ms.json.JacksonJsonHandler Maven / Gradle / Ivy

/*
 * 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
 *
 *     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 io.github.honhimw.ms.json;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.databind.module.SimpleDeserializers;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import lombok.Getter;

import java.io.IOException;
import java.lang.reflect.Type;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.TimeZone;

import static io.github.honhimw.ms.support.DateTimeUtils.RFC_3339;
import static io.github.honhimw.ms.support.DateTimeUtils.RFC_3339_FORMATTER;

/**
 * @author hon_him
 * @since 2023-12-29
 */

@Getter
public class JacksonJsonHandler implements JsonHandler {

    private final JsonMapper jsonMapper;

    public JacksonJsonHandler() {
        this(defaultBuilder().build());
    }

    public JacksonJsonHandler(JsonMapper jsonMapper) {
        this.jsonMapper = jsonMapper;
    }

    @SuppressWarnings("rawtypes")
    public static JsonMapper.Builder defaultBuilder() {
        JsonMapper.Builder builder = JsonMapper.builder();

        builder.serializationInclusion(JsonInclude.Include.NON_NULL);
        JavaTimeModule javaTimeModule = new JavaTimeModule();
        javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ISO_DATE)); //yyyy-MM-dd
        javaTimeModule.addDeserializer(LocalDate.class,
            new LocalDateDeserializer(DateTimeFormatter.ISO_DATE)); //yyyy-MM-dd

        javaTimeModule.addSerializer(LocalDateTime.class,
            new LocalDateTimeSerializer(RFC_3339_FORMATTER));
        javaTimeModule.addDeserializer(LocalDateTime.class,
            new LocalDateTimeDeserializer(RFC_3339_FORMATTER));
        javaTimeModule.addSerializer(Date.class, new JsonSerializer() {
            @Override
            public void serialize(Date value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
                SimpleDateFormat formatter = new SimpleDateFormat(RFC_3339);
                String formattedDate = formatter.format(value);
                gen.writeString(formattedDate);
            }
        }).addDeserializer(Date.class, new JsonDeserializer() {
            @Override
            public Date deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
                String text = p.getText();
                SimpleDateFormat formatter = new SimpleDateFormat(RFC_3339);
                try {
                    return formatter.parse(text);
                } catch (ParseException e) {
                    throw new IOException(e);
                }
            }
        });

        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addSerializer(Long.class, ToStringSerializer.instance);
        simpleModule.addSerializer(Long.TYPE, ToStringSerializer.instance);

        simpleModule.addSerializer(EnumValue.class, new JsonSerializer() {
            @Override
            public void serialize(EnumValue value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
                gen.writeString(value.value());
            }
        });
        simpleModule
            .setDeserializers(new SimpleDeserializers() {
                @Override
                public JsonDeserializer findEnumDeserializer(Class type, DeserializationConfig config, BeanDescription beanDesc) throws JsonMappingException {
                    if (EnumValue.class.isAssignableFrom(type)) {
                        final Map> map = new HashMap<>();
                        Object[] enumConstants = type.getEnumConstants();
                        for (Object enumConstant : enumConstants) {
                            map.put(((EnumValue) enumConstant).value(), (Enum) enumConstant);
                        }
                        return new JsonDeserializer>() {
                            @Override
                            public Enum deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
                                String text = p.getText();
                                return map.get(text);
                            }
                        };
                    }
                    return super.findEnumDeserializer(type, config, beanDesc);
                }
            });

        builder
            .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
            .defaultDateFormat(new SimpleDateFormat(RFC_3339))
            .addModules(javaTimeModule, simpleModule)
            .defaultTimeZone(TimeZone.getDefault())
        ;
        return builder;
    }

    @Override
    public String toJson(Object o) {
        try {
            return jsonMapper.writeValueAsString(o);
        } catch (Exception e) {
            throw new IllegalArgumentException("json encode exception", e);
        }
    }

    @Override
    public  T fromJson(String json, Class tClass) {
        try {
            return jsonMapper.readValue(json, tClass);
        } catch (Exception e) {
            throw new IllegalArgumentException("json decode exception", e);
        }
    }

    @Override
    public  T fromJson(String json, TypeRef typeRef) {
        try {
            return jsonMapper.readValue(json, new TypeReference() {
                @Override
                public Type getType() {
                    return typeRef.getType();
                }
            });
        } catch (Exception e) {
            throw new IllegalArgumentException("json decode exception", e);
        }
    }

    @Override
    public  T transform(Object o, TypeRef typeRef) {
        try {
            return jsonMapper.convertValue(o, new TypeReference() {
                @Override
                public Type getType() {
                    return typeRef.getType();
                }
            });
        } catch (Exception e) {
            throw new IllegalArgumentException("json decode exception", e);
        }
    }

    public JsonMapper getJsonMapper() {
        return jsonMapper;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy