2020-06-08

Java Jdk8 suportted JacksonUtil

Worries about XML and JSON processing

When processing json and xml data in java, there are various third-party libraries for users to choose. Among them are Gson, FastJson, Jackson, Json-lib, xstream, jaxb and so on.
Because there are so many options available in Java, if you choose a library to handle json and xml at will, it will not only cause code confusion and difficult to maintain, but also make your jar or war expand in size and increase the release cost.

Use Jackson

In order to avoid such disasters, we have to find a way to unify the libraries used by programmers when dealing with json and xml data. It is precisely Jackson that is the leader in the above third-party libraries in terms of ease of use, efficiency, and community activity, which can meet our needs.

Excellent common-Utils can often support the latest API, and the latest jackson library has fully supported the new date API in jdk8.
To use jackson that supports jdk8 date processing API, you need to import the following versions, or the above version of the library.

Annotation support in Jackson

One of the great advantages of using jackson to process xml and json is that the annotations used during serialization are universal. The same annotation can take effect with the serialization and deserialization of json and xml.

@JsonIgnoreProperties({"extra"})
class annotation. When deserializing json data, the corresponding json keys in the annotation parameters can be ignored. Using @JsonIgnoreProperties(ignoreUnknown=true) can ignore all unknown elements.

@JsonSerialize(using = JacksonUtil.JsonLocalDateSerializer.class)
attribute annotation. When you need to use a custom serialization and deserialization parser, use this annotation to modify class member variables.

@JsonIgnore
attribute annotation. The members modified by this annotation are ignored during serialization and deserialization.

@JsonProperty("firstName")
attribute annotation. Use aliases when serializing and deserializing.

Custom serialization and deserialization parser##
By inheriting JsonSerializer and JsonDeserializer, we can implement our own parser. Usually your own parser is used to deal with the problem of mapping a json string to the DateTime type attribute of pojo.


Serialization


/**
     *
     * LocalDateTime
     * jdk8 support
     */
    public static class JsonLocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {


        @Override
        public void serialize(LocalDateTime localDateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
            String localdateTimeStr = localDateTime.format(DateTimeFormatter.ISO_DATE_TIME);
            jsonGenerator.writeString(localdateTimeStr);
        }
    }

Deserialization

/**
     *
     * LocalDateTime
     * jdk8 support
     */
    public static class JsonLocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {


        @Override
        public LocalDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
            String str = jsonParser.getText().trim();
            return LocalDateTime.parse(str, DateTimeFormatter.ISO_DATE_TIME);
        }
    }

Class TypeFactory

When trying to convert a jsonArray to pojoList you will encounter some minor troubles.
You must first create a JavaType object using the factory method, and then tell jackson what you want the deserialized object to look like based on the JavaType object you created.

 /**
     * json PojoList
     *
     * @param jsonStr json
     * @param cls   
     * @param <T>   
     * @return pojoList
     */
    public static <T> List<T> jsonArray2PojoList(String jsonStr, Class<T> cls) {
        List<T> pojoList = null;
        try {
            CollectionType listType = objectMapper.getTypeFactory().constructCollectionType(List.class, cls);
            pojoList = objectMapper.readValue(jsonStr, listType);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return pojoList;
    }

Class TypeReference<T>

Jackson needs to get the bytecode object of the object when deserializing the object. Usually use Object.class to solve this problem. However, when the deserialized object you expect is a generic object, due to the problem of generic compensation and erasure, you cannot get the bytecode object using List<>.class. How is it good?
Check the documentation to see if you can get help.

This generic abstract class is used for obtaining full generics type information by sub-classing; it must be converted to ResolvedType implementation (implemented by JavaType from "databind" bundle) to be used.

According to the description of the document, we can get the information of the generic class through TypeReference.

/**
     * json listMap
     *
     * @param jsonArray jsonArray
     * @return Listmap
     */
    public static List<Map<String, Object>> jsonArray2ListMap(String jsonArray) {
        List<Map<String, Object>> convertedListMap = null;
        try {
            convertedListMap = objectMapper.readValue(jsonArray, new TypeReference<List<Map<String, Object>>>() {
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
        return convertedListMap;
    }

A complete JacksonUtil

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.type.CollectionType;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;

import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;


/**
 * XML,JSON
 * jackson pojo2json/xml
 *
 * @author lincanhan
 */

final public class JacksonUtil {


    private static ObjectMapper objectMapper = new ObjectMapper();

    private static ObjectMapper xmlMapper = new XmlMapper();


    /**
     *
     */
    private JacksonUtil() {
        throw new AssertionError();
    }

    /**
     *
     * LocalDateTime
     * jdk8 support
     */
    public static class JsonLocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {


        @Override
        public void serialize(LocalDateTime localDateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
            String localdateTimeStr = localDateTime.format(DateTimeFormatter.ISO_DATE_TIME);
            jsonGenerator.writeString(localdateTimeStr);
        }
    }

    /**
     *
     * LocalDateTime
     * jdk8 support
     */
    public static class JsonLocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {


        @Override
        public LocalDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
            String str = jsonParser.getText().trim();
            return LocalDateTime.parse(str, DateTimeFormatter.ISO_DATE_TIME);
        }
    }

    /**
     *
     * LocalDate
     * jdk8 support
     */
    public static class JsonLocalDateDeserializer extends JsonDeserializer<LocalDate> {

        @Override
        public LocalDate deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
            String str = jsonParser.getText().trim();
            return LocalDate.parse(str, DateTimeFormatter.ISO_DATE);
        }
    }

    /**
     *
     * LocalDate
     * jdk8 support
     */
    public static class JsonLocalDateSerializer extends JsonSerializer<LocalDate> {


        @Override
        public void serialize(LocalDate localDate, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
            String localdateStr = localDate.format(DateTimeFormatter.ISO_DATE);
            jsonGenerator.writeString(localdateStr);
        }
    }

    /**
     * json pojo
     *
     * @param jsonStr json
     * @param cls   
     * @param <T>   
     * @return json
     */
    public static <T> T json2Pojo(String jsonStr, Class<T> cls) {
        T object = null;
        try {
            object = objectMapper.readValue(jsonStr, cls);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return object;
    }


    /**
     * json PojoList
     *
     * @param jsonStr json
     * @param cls   
     * @param <T>   
     * @return pojoList
     */
    public static <T> List<T> jsonArray2PojoList(String jsonStr, Class<T> cls) {
        List<T> pojoList = null;
        try {
            CollectionType listType = objectMapper.getTypeFactory().constructCollectionType(List.class, cls);
            pojoList = objectMapper.readValue(jsonStr, listType);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return pojoList;
    }


    /**
     * pojo json
     *
     * @param obj pojo
     * @return json字符串
     */
    public static String pojo2Json(Object obj) {
        String jsonStr = "";
        try {
            jsonStr = objectMapper.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return jsonStr;
    }

    /**
     * json listMap
     *
     * @param jsonArray jsonArray
     * @return Listmap
     */
    public static List<Map<String, Object>> jsonArray2ListMap(String jsonArray) {
        List<Map<String, Object>> convertedListMap = null;
        try {
            convertedListMap = objectMapper.readValue(jsonArray, new TypeReference<List<Map<String, Object>>>() {
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
        return convertedListMap;
    }

    /**
     * json map
     *
     * @param json json
     * @return map
     */
    public static Map<String, Object> json2Map(String json) {
        Map<String, Object> convertedMap = null;
        try {
            convertedMap = objectMapper.readValue(json, new TypeReference<Map<String, Object>>() {
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
        return convertedMap;
    }


    /**
     * listMap json
     *
     * @param listMap listMap
     * @return
     */
    public static String listMap2JsonArray(List<Map<String, Object>> listMap) {
        String jsonStr = "";
        try {
            jsonStr = objectMapper.writeValueAsString(listMap);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return jsonStr;
    }


    /**
     * xml pojo
     *
     * @param xmlStr xml
     * @param cls   
     * @param <T>   
     * @return pojo
     */
    public static <T> T xml2Pojo(String xmlStr, Class<T> cls) {
        T pojo = null;
        try {
            pojo = xmlMapper.readValue(xmlStr, cls);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return pojo;
    }

    /**
     * xml pojoList
     *
     * @param xmlStr xml
     * @param cls   
     * @param <T>   
     * @return pojo
     */
    public static <T> List<T> xml2PojoList(String xmlStr, Class<T> cls) {
        CollectionType listType = objectMapper.getTypeFactory().constructCollectionType(List.class, cls);
        List<T> pojoList = null;
        try {
            pojoList = xmlMapper.readValue(xmlStr, listType);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return pojoList;
    }


    /**
     * pojo转xml
     *
     * @param object
     */
    public static String pojo2Xml(Object object) {
        String xml = "";
        try {
            xml = xmlMapper.writeValueAsString(object);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return xml;
    }


    /**
     * xml map
     *
     * @param xmlStr xml
     * @return map
     */
    public static Map<String, Object> xml2Map(String xmlStr) {
        Map<String, Object> map = null;
        try {
            map = xmlMapper.readValue(xmlStr, new TypeReference<Map<String, Object>>() {
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
        return map;
    }

    /**
     * xmlListMap
     *
     * @param xmlStr xml
     * @return map
     */
    public static List<Map<String, Object>> xml2ListMap(String xmlStr) {
        List<Map<String, Object>> listMap = null;
        try {
            listMap = xmlMapper.readValue(xmlStr, new TypeReference<List<Map<String, Object>>>() {
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
        return listMap;
    }

}


import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import jackson.JacksonUtil;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Arrays;


//@JsonIgnoreProperties(ignoreUnknown=true)忽略所有未知元素
@JsonIgnoreProperties({"extra"})
public class User {

   
    private Gender gender;

    private Name name;

    private boolean isVerified;

    private byte[] userImage;

    @JsonSerialize(using = JacksonUtil.JsonLocalDateSerializer.class)
    @JsonDeserialize(using = JacksonUtil.JsonLocalDateDeserializer.class)
    private LocalDate birthday;

    @JsonSerialize(using = JacksonUtil.JsonLocalDateTimeSerializer.class)
    @JsonDeserialize(using = JacksonUtil.JsonLocalDateTimeDeserializer.class)
    private LocalDateTime loginTime;


    @JsonIgnore
    private String note;

    public enum Gender {
        MALE, FEMALE
    }

    public static class Name {

        private String first;

        //@JsonProperty("LAST")
        private String last;


        public String getFirst() {
            return first;
        }

        public void setFirst(String first) {
            this.first = first;
        }

        public String getLast() {
            return last;
        }

        public void setLast(String last) {
            this.last = last;
        }

        @Override
        public String toString() {
            return "Name{" +
                    "first='" + first + '\'' +
                    ", last='" + last + '\'' +
                    '}';
        }
    }


    public LocalDate getBirthday() {
        return birthday;
    }

    public void setBirthday(LocalDate birthday) {
        this.birthday = birthday;
    }

    public LocalDateTime getLoginTime() {
        return loginTime;
    }

    public void setLoginTime(LocalDateTime loginTime) {
        this.loginTime = loginTime;
    }

    public String getNote() {
        return note;
    }

    public void setNote(String note) {
        this.note = note;
    }

    public Gender getGender() {
        return gender;
    }

    public void setGender(Gender gender) {
        this.gender = gender;
    }

    public Name getName() {
        return name;
    }

    public void setName(Name name) {
        this.name = name;
    }

    public boolean isVerified() {
        return isVerified;
    }

    public void setVerified(boolean verified) {
        this.isVerified = verified;
    }

    public byte[] getUserImage() {
        return userImage;
    }

    public void setUserImage(byte[] userImage) {
        this.userImage = userImage;
    }

    @Override
    public String toString() {
        return "User{" +
                "gender=" + gender +
                ", name=" + name +
                ", isVerified=" + isVerified +
                ", userImage=" + Arrays.toString(userImage) +
                '}';
    }


}


It is not just jacksonUtil, the standard use of dateUtil, HttpClientUtil and other common Utils in the project can greatly enhance the maintainability of the project, reduce the probability of bugs, reduce the size of the project, and reduce the cost of release.
Based on such considerations, I have created common-Utils as an open source project . If you also have safe, efficient, fully-commented and highly maintainable Utils , welcome to share with you!

No comments:

Post a Comment