美文网首页
Jackson使用POJO简单对象生成JSON

Jackson使用POJO简单对象生成JSON

作者: 木木与呆呆 | 来源:发表于2021-11-19 11:21 被阅读0次

    1.说明

    在开发中,经常需要测试Restful接口,
    需要生成POJO简单对象的JSON字符串,
    如果对象类的字段比较多,
    手工生成的时候会很麻烦,
    下面提供一个基于Jackson的工具类,
    能够根据POJO简单对象类,
    初始化对象类中字段的默认值,
    然后生成JSON字符串。

    2.POJO简单对象

    简单对象类UserEntity.java如下,
    省略了get/set/toString等方法:

    package com.yuwen.spring.demo.entity;
    import com.baomidou.mybatisplus.annotation.IdType;
    import com.baomidou.mybatisplus.annotation.TableField;
    import com.baomidou.mybatisplus.annotation.TableId;
    import com.baomidou.mybatisplus.annotation.TableName;
    import java.io.Serializable;
    import java.time.LocalDate;
    import java.time.LocalDateTime;
    /**
     * 用户实体类
     */
    public class UserEntity implements Serializable {
        private static final long serialVersionUID = 1L;
    
        /**
         * 用户ID
         */
        private Long id;
        /**
         * 姓名
         */
        private String name;
        /**
         * 邮箱
         */
        private String email;
        /**
         * 生日
         */
        private LocalDate birthday;
        /**
         * 创建时间
         */
        private LocalDateTime createTime;
        /**
         * 修改时间
         */
        private LocalDateTime updateTime;
    }
    

    3.Jackson工具类

    工具类JacksonJsonGenerator.java如下,
    每次使用的时候只需要修改targetClass:

    package com.yuwen.spring.jackson.generator;
    import java.lang.reflect.Field;
    import java.lang.reflect.Modifier;
    import java.time.LocalDate;
    import java.time.LocalDateTime;
    import java.time.LocalTime;
    import java.time.format.DateTimeFormatter;
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.util.ReflectionUtils;
    import org.springframework.util.ReflectionUtils.FieldCallback;
    import com.fasterxml.jackson.core.JsonProcessingException;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
    import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
    import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
    import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
    import com.yuwen.spring.demo.entity.UserEntity;
    
    /**
     * 使用Jackson,指定Java的POJO简单对象类,生成对应的JSON字符串
     */
    public class JacksonJsonGenerator {
        // 指定需要生成JSON的Java类
        public static Class<?> targetClass = UserEntity.class;
    
        public static void main(String[] args) throws Exception {
            Object object = initObjectDefaultValue(targetClass);
    
            genetateJson(object);
        }
    
        /**
         * 初始化对象字段的默认值
         */
        private static Object initObjectDefaultValue(Class<?> targetClass)
                throws InstantiationException, IllegalAccessException {
            Object object = targetClass.newInstance();
    
            // 根据属性类型给属性设默认值
            FieldCallback fc = new FieldCallback() {
                @Override
                public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
                    Class<?> fieldType = field.getType();
    
                    // final修饰的字段无法设置新的值
                    if (Modifier.isFinal(field.getModifiers())) {
                        return;
                    }
    
                    String type = fieldType.getSimpleName();
                    Object fieldValue = StringUtils.EMPTY;
                    switch (type) {
                    case "String":
                        fieldValue = StringUtils.EMPTY;
                        break;
                    case "int":
                    case "Integer":
                        fieldValue = 0;
                        break;
                    case "long":
                    case "Long":
                        fieldValue = 0L;
                        break;
                    case "LocalDate":
                        fieldValue = LocalDate.now();
                        break;
                    case "LocalDateTime":
                        fieldValue = LocalDateTime.now();
                        break;
                    default:
                        fieldValue = StringUtils.EMPTY;
                        break;
                    }
                    try {
                        field.setAccessible(true);
                        field.set(object, fieldValue);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            };
            ReflectionUtils.doWithFields(targetClass, fc);
            return object;
        }
    
        /**
         * 生成对象的JSON字符串
         */
        private static void genetateJson(Object object) throws JsonProcessingException {
            System.out.println("POJO对象:");
            System.out.println(object);
    
            ObjectMapper mapper = new ObjectMapper();
            // 用于序列化Java8新的时间类型
            JavaTimeModule javaTimeModule = new JavaTimeModule();
            javaTimeModule.addSerializer(LocalDateTime.class,
                    new LocalDateTimeSerializer(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
            javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ISO_LOCAL_DATE));
            javaTimeModule.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ISO_LOCAL_DATE));
            mapper.registerModule(javaTimeModule);
            String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(object);
    
            System.out.println("JSON字符串:");
            System.out.println(json);
        }
    }
    

    4.生成JSON字符串

    运行main方法输出结果:

    POJO对象:
    UserEntity{id=0, name=, email=, birthday=2021-11-19, 
    createTime=2021-11-19T15:10:32.874, updateTime=2021-11-19T15:10:32.874}
    JSON字符串:
    {
      "id" : 0,
      "name" : "",
      "email" : "",
      "birthday" : "2021-11-19",
      "createTime" : "2021-11-19T15:10:32.874",
      "updateTime" : "2021-11-19T15:10:32.874"
    }
    

    5.更多的数据类型

    在initObjectDefaultValue方法中,
    修改swith-case增加更多的case,
    可以支持更多的数据类型,
    也可以修改类型对应的默认值。

    6.问题解决

    Jackson无法序列化Java8新的时间类型,
    异常如下:

    Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidDefinitionException: 
    Java 8 date/time type `java.time.LocalDate` not supported by default: 
    add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling
     (through reference chain: com.yuwen.spring.demo.entity.UserEntity["birthday"])
    

    因为birthday字段为LocalDate类型,
    按照提示在pom.xml新增
    如下依赖:

    <dependency>
      <groupId>com.fasterxml.jackson.datatype</groupId>
      <artifactId>jackson-datatype-jsr310</artifactId>
      <version>2.12.5</version>
    </dependency>
    

    然后在ObjectMapper注册JavaTimeModule即可:

    ObjectMapper mapper = new ObjectMapper();
    mapper.registerModule(new JavaTimeModule());
    

    7.其他方案

    使用Jsr310NullKeySerializer,
    也可以设置字段值为NULL时的序列化动作,
    但是只能设置为""空字符串,
    同时由于无法获取值为NULL的字段的类型,
    无法为数据类型设置对应的默认值。
    Jsr310NullKeySerializer.java代码如下:

    package com.fasterxml.jackson.datatype.jsr310.ser.key;
    import java.io.IOException;
    import java.util.Map;
    import com.fasterxml.jackson.core.JsonGenerator;
    import com.fasterxml.jackson.databind.JsonMappingException;
    import com.fasterxml.jackson.databind.JsonSerializer;
    import com.fasterxml.jackson.databind.SerializerProvider;
    
    /**
     * This class is to be used in case {@code null} keys are needed to be serialized in a {@link Map} with Java 8 temporal keys. By default the
     * {@code null} key is not supported by jackson, the serializer needs to be registered manually.
     *
     * @author Zoltan Kiss
     * @since 2.6
     */
    @Deprecated // since 2.10 -- not sure why module should provide general purpose null serializer
    //   (maybe add in databind)
    public class Jsr310NullKeySerializer extends JsonSerializer<Object> {
    
        public static final String NULL_KEY = "";
        @Override
        public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException
        {
            if (value != null) {
                throw JsonMappingException.from(gen,
                        "Jsr310NullKeySerializer is only for serializing null values.");
            }
            gen.writeFieldName(NULL_KEY);
        }
    }
    

    相关文章

      网友评论

          本文标题:Jackson使用POJO简单对象生成JSON

          本文链接:https://www.haomeiwen.com/subject/fjbstrtx.html