Jackson 学习使用


文章目录

  • Jackson 学习使用
  • Jackson 优点
  • Jackson 的核心模块
  • 引入 Jackson 依赖
  • 多态类型的序列化及反序列化
  • @JsonTypeInfo
  • ObjectMapper可设置的属性
  • JackSonUtils
  • JackSon常用注解


  • Jackson是一个简单基于Java应用库,Jackson可以轻松的将Java对象转换成json对象和xml文档,同样也可以将json、xml转换成Java对象。Jackson所依赖的jar包较少,简单易用并且性能也要相对高些,并且Jackson社区相对比较活跃,更新速度也比较快。

Jackson 优点

  • 解析大文件的速度比较快;
  • 运行时占用的内存比较少,性能更佳;
  • API 很灵活,容易进行扩展和定制

Jackson 的核心模块

  • jackson-core:核心包,提供基于“流模式”解析的相关 API,包括 JsonPaserJsonGenerator
  • jackson-annotations:注解包,提供标准的注解功能;
  • jackson-databind :数据绑定包,提供基于“对象绑定”解析的相关 API 和基于“树模型”解析的相关 API

引入 Jackson 依赖

要想使用 Jackson,需要在 pom.xml 文件中添加 Jackson 的依赖。

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.10.1</version>
</dependency>

jackson-databind 依赖于 jackson-core 和 ~,所以添加完 jackson-databind 之后,Maven 会自动将 jackson-corejackson-annotations 引入到项目当中。

多态类型的序列化及反序列化

  • 要对json对象进行反序列化操作,但是我们并不知知道具体的json格式,也就是说我们不知道json有哪些字段。
  • 解析抽象类或者接口

@JsonTypeInfo

  • Animal抽象类:使用 JsonTypeInfo注解配置反序列化的规则
@JsonTypeInfo(
        use = JsonTypeInfo.Id.NAME,
        property = "name",
        visible = true,
        include = JsonTypeInfo.As.EXISTING_PROPERTY)
@JsonSubTypes({
        @JsonSubTypes.Type(value = Dog.class, name = "dog"),
        @JsonSubTypes.Type(value = Cat.class, name = "cat")
})
public abstract class Animal {

    private String name;
    private String id;
 	// getset   
}
  • Cat子类
public class Cat extends Animal{

    private String speed;
    
}
  • Dog子类
public class Dog extends Animal{

    private String food;
    
}
  • 测试类
@Test
public void test1() {
    String tempStr = "{\"speed\":\"100\",\"name\":\"cat\",\"food\":\"dogfood\"}";
    ObjectMapper mapper = new ObjectMapper();
    // 配置忽略未知属性
    mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    try {
        Dog dog = (Dog) mapper.readValue(tempStr, Animal.class);
        logger.info("cat:{} ", dog.toString());
    } catch (IOException e) {
        throw new RuntimeException(e);
    }
}

ObjectMapper可设置的属性

ObjectMapper objectMapper = new ObjectMapper();
// 属性为Null的不进行序列化,只对pojo起作用,对map和list不起作用
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
// json进行换行缩进等操作
objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
// json不进行换行缩进等操作  默认就是不进行操作,写了这行和没写的效果一样
objectMapper.disable(SerializationFeature.INDENT_OUTPUT);
// json是否允许属性名没有引号 ,默认是false
objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
//json是否允许属性名为单引号 ,默认是false
objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
// 遇到未知属性是否抛出异常 ,默认是抛出异常的
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// 当实体类没有setter方法时,序列化不报错,返回一个空对象
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
// 所有的字母小写,没有分隔符,例如 lowercase
objectMapper.setPropertyNamingStrategy(PropertyNamingStrategy.LOWER_CASE);
//序列化的时候序列对象的所有属性
objectMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);
//取消时间的转化格式,默认是时间戳,可以取消,同时需要设置要表现的时间格式
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
// 设置日期格式化
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));

JackSonUtils

public class JackSonUtils {

    private static Logger logger = LoggerFactory.getLogger(JackSonUtils.class);

    private static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";

    private static final ConcurrentHashMap<String, ObjectMapper> mapperMap = new ConcurrentHashMap<>();

    /**
     * 对象转json字符串
     *
     * @param object object
     * @return String
     */
    public static String toJSONString(Object object) {
        return toJSONString(object, YYYY_MM_DD_HH_MM_SS, false);
    }

    /**
     * 对象转json字符串, 是否美化输出
     *
     * @param object       object
     * @param prettyFormat 是否美化输出
     * @return String
     */
    public static String toJSONString(Object object, boolean prettyFormat) {
        return toJSONString(object, YYYY_MM_DD_HH_MM_SS, prettyFormat);
    }

    /**
     * 对象转json字符串,指定日期格式
     *
     * @param object           object
     * @param dataFormatString 时间格式化
     * @return String
     */
    public static String toJSONString(Object object, String dataFormatString) {
        return toJSONString(object, dataFormatString, false);
    }

    /**
     * 对象转json字符串,指定日期格式, 是否美化输出
     *
     * @param object           object
     * @param dataFormatString 时间格式化
     * @param prettyFormat     是否美化格式
     * @return String
     */
    public static String toJSONString(Object object, String dataFormatString, boolean prettyFormat) {
        return toJSONString(object, dataFormatString, prettyFormat, JsonInclude.Include.NON_NULL);
    }

    /**
     * 对象转json字符串,空值处理
     */
    public static String toJSONString(Object object, JsonInclude.Include include) {
        return toJSONString(object, YYYY_MM_DD_HH_MM_SS, false, include);
    }

    /**
     * 对象转json字符串,指定日期格式, 空值处理
     */
    public static String toJSONString(Object object, String dataFormatString, JsonInclude.Include include) {
        return toJSONString(object, dataFormatString, false, include);
    }

    /**
     * 对象转json字符串,指定日期格式, 是否美化输出, 空值处理
     *
     * @param object           object
     * @param dataFormatString 时间日期格式化
     * @param prettyFormat     是否美化输出
     * @param include          include
     * @return String
     */
    public static String toJSONString(Object object, String dataFormatString, boolean prettyFormat, JsonInclude.Include include) {
        if (ObjectUtils.isEmpty(object)) {
            return null;
        }
        if (!StringUtils.hasText(dataFormatString)) {
            dataFormatString = YYYY_MM_DD_HH_MM_SS;
        }
        ObjectMapper objectMapper = getObjectMapper(dataFormatString, prettyFormat, include);
        try {
            return objectMapper.writeValueAsString(object);
        } catch (JsonProcessingException e) {
            logger.error(e.getMessage(), e);
        }
        return null;
    }

    /**
     * 将json字符串转换成ObjectNode对象
     *
     * @param content content
     */
    public static ObjectNode parseObject(String content) {
        return parseObject(content, ObjectNode.class);
    }

    /**
     * 将json字符串转换成指定类型对象
     *
     * @param <T>     T
     * @param content 内容
     */
    public static <T> T parseObject(String content, Class<T> valueType) {
        if (!StringUtils.hasText(content)) {
            return null;
        }
        ObjectMapper objectMapper = getObjectMapper();
        try {
            return objectMapper.readValue(content, valueType);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return null;
    }

    /**
     * 将json字符串转换成ArrayNode数组
     */
    public static ArrayNode parseArray(String content) {
        return parseObject(content, ArrayNode.class);
    }

    /**
     * 将json字符串转换成指定类型对象数组
     */
    public static <T> List<T> parseArray(String content, Class<T> valueType) {
        if (!StringUtils.hasText(content)) {
            return null;
        }
        ObjectMapper objectMapper = getObjectMapper();
        try {
            CollectionType javaType = objectMapper.getTypeFactory().constructCollectionType(List.class, valueType);
            return objectMapper.readValue(content, javaType);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return null;
    }

    /**
     * 将json字符串转换成Map
     *
     * @param content c
     * @param content
     */
    public static Map<String, Object> parseMap(String content) {
        return parseMap(content, String.class, Object.class);
    }

    /**
     * 将json字符串转换成Map, 指定泛型
     */
    public static <K, V> Map<K, V> parseMap(String content, Class<K> keyType, Class<V> valueType) {
        if (!StringUtils.hasText(content)) {
            return null;
        }

        ObjectMapper objectMapper = getObjectMapper();

        try {
            MapType javaType = objectMapper.getTypeFactory().constructMapType(Map.class, keyType, valueType);
            return objectMapper.readValue(content, javaType);
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return null;
    }

    /**
     * 将json字符串转换成Map数组
     *
     * @param content content
     * @return List
     */
    public static List<Map<String, Object>> parseMapArray(String content) {
        return parseMapArray(content, String.class, Object.class);
    }

    /**
     * 将json字符串转换成Map数组, 指定泛型
     */
    public static <K, V> List<Map<K, V>> parseMapArray(String content, Class<K> keyType, Class<V> valueType) {
        if (!StringUtils.hasText(content)) {
            return null;
        }
        ObjectMapper objectMapper = getObjectMapper();
        try {
            TypeFactory typeFactory = objectMapper.getTypeFactory();
            MapType mapType = typeFactory.constructMapType(Map.class, keyType, valueType);
            CollectionType collectionType = objectMapper.getTypeFactory().constructCollectionType(List.class, mapType);
            return objectMapper.readValue(content, collectionType);
        } catch (JsonMappingException e) {
            logger.error("JsonMappingException: ", e);
        } catch (JsonProcessingException e) {
            logger.error("JsonProcessingException: ", e);
        }
        return null;
    }

    /**
     * 获取 ObjectMapper
     *
     * @return ObjectMapper
     */
    private static ObjectMapper getObjectMapper() {
        return getObjectMapper(YYYY_MM_DD_HH_MM_SS, false, JsonInclude.Include.NON_NULL);
    }

    /**
     * 获取 ObjectMapper
     *
     * @param dataFormatString 时间格式化格式
     * @param prettyFormat     是否美化输出
     * @param include          include
     * @return ObjectMapper
     */
    private static ObjectMapper getObjectMapper(String dataFormatString, boolean prettyFormat, JsonInclude.Include include) {
        String key = prettyFormat ? "P#" + dataFormatString : dataFormatString;
        ObjectMapper objectMapper = mapperMap.get(key);
        if (objectMapper != null) {
            return objectMapper;
        }
        mapperMap.putIfAbsent(key, new ObjectMapper());
        objectMapper = mapperMap.get(key);
        objectMapper.setSerializationInclusion(include);
        // 忽略未知映射
        objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        // 日期格式
        objectMapper.setDateFormat(new SimpleDateFormat(dataFormatString));
        // 美化输出
        if (prettyFormat) {
            objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
        }
        // 处理 BigDecimal 精度问题
        SimpleModule module = new SimpleModule();
        module.addSerializer(BigDecimal.class, new BigDecimalJsonSerializer());
        // 处理 Double 科学计数法
        module.addSerializer(Double.class, new DoubleJsonSerializer());
        objectMapper.registerModule(module);
        return objectMapper;
    }

    /**
     * BigDecimal 类型的序列设置
     */
    private static class BigDecimalJsonSerializer extends JsonSerializer<BigDecimal> {

        public void serialize(BigDecimal t, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
            if (null == t) {
                jsonGenerator.writeNull();
            } else {
                String valStr = t.toPlainString();
                if (valStr.length() > 16) {
                    jsonGenerator.writeString(valStr);
                } else {
                    jsonGenerator.writeNumber(t);
                }
            }
        }
    }

    /**
     * Double 类型的序列化设置
     */
    private static class DoubleJsonSerializer extends JsonSerializer<Double> {

        public void serialize(Double value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
            if (value == null) {
                gen.writeNull();
            } else {
                String valStr = value.toString();
                if (valStr.contains("E")) {
                    gen.writeString(new BigDecimal(valStr).toPlainString());
                } else {
                    gen.writeNumber(value.doubleValue());
                }
            }
        }
    }
}

JackSon常用注解

注解

用法

@JsonProperty

用于属性,把属性的名称序列化时转换为另外一个名称。示例: @JsonProperty("birthDateTime") private Date birthDate;

@JsonFormat

用于属性或者方法,把属性的格式序列化时转换成指定的格式。示例: @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm") public Date getBirthDate()

  • @JsonIgnore:序列化时忽略此字段
  • @JsonIgnorePropertiesJackson注解用于指定要忽略的类的属性列表。 @JsonIgnoreProperties注解放置在类声明上方,而不是要忽略的各个属性(字段)上方。