Jackson

作者: 十二找十三 | 来源:发表于2022-06-20 11:42 被阅读0次

基础

1.jackson的github地址:https://github.com/FasterXML/jackson
2.jackson共有1.x和2.x两个版本系列, 其中1.x已废弃不再有版本发布, 2.x是活跃版本, 1.x和2.x并不兼容但也不冲突可以同时使用    
3.jackson有三个核心模块
    jackson-core -> 低阶API库,提供流式解析工具JsonParser,流式生成工具JsonGenerator
    jackson-annotations -> jackson注解
    jackson-databind -> 基于java对象的序列化, 反序列化能力, 需要前面两个模块的支持才能实现

<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.13.3</version>
</dependency>

spring boot 已经自动集成 如果是Spring 项目根本不需要引依赖

jackson-core 相关知识

相关核心API
    private static JsonFactory jsonFactory = new JsonFactory(); // 线程安全的 可以全局公用一个

    /**
     * jsonStr to Object
     * 反序列化测试(JSON STR -> Object),入参是JSON字符串
     */
    private static Object deserializeJSONByStr(String jsonString) {
        JsonParser jsonParser = null;

        Object object = new Object(); // 可以声明自己想要的对象类型 然后返回 就是转换成指定类型

        try {
            jsonParser = jsonFactory.createParser(jsonString);

            if (jsonParser.nextToken() != JsonToken.START_OBJECT) {
                jsonParser.close();
                throw new IOException("起始位置没有大括号{");
            }

            while ( jsonParser.nextToken() != JsonToken.END_OBJECT) {

                String fieldName = jsonParser.getCurrentName(); // 当前正在解析字段
                jsonParser.nextToken(); // * next 解析下一个


                /**
                 * 可以获取多种类型
                 * jsonParser.getLongValue()
                 * jsonParser.getText()
                 * jsonParser.getIntValue()
                 * jsonParser.getBooleanValue()
                 */
                String fieldValue = jsonParser.getValueAsString();

                System.out.println(fieldName + "->" + fieldValue);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return object;
    }


    /**
     * 序列化测试(Object -> JSON)
     *
     * @return 由对象序列化得到的JSON字符串
     */
    public static String serialize(Map<String, Object> obj) {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

        try (JsonGenerator jsonGenerator = jsonFactory.createGenerator(byteArrayOutputStream, JsonEncoding.UTF8)) {

            jsonGenerator.useDefaultPrettyPrinter();

            jsonGenerator.writeStartObject();
            jsonGenerator.writeNumberField("id", (int) obj.get("id"));
            jsonGenerator.writeStringField("str", (String) obj.get("str"));
            jsonGenerator.writeEndObject();
        } catch (IOException e) {
            e.printStackTrace();
        }
        
        return byteArrayOutputStream.toString();
    }



-------------------------------------------------------------------测试类---------------------------------------------

package com.study.other;

import com.fasterxml.jackson.core.*;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class JacksonCoreTest {

    public static void main(String[] args) {
        String str = "{\"aaa\":\"1\", \"bbb\":2}";
        System.out.println(deserializeJSONByStr(str));

        Map<String, Object> obj = new HashMap<>();
        obj.put("id", 1);
        obj.put("str", "2");
        System.out.println(serialize(obj));
    }

    private static JsonFactory jsonFactory = new JsonFactory();

    /**
     * 序列化测试(Object -> JSON)
     *
     * @return 由对象序列化得到的JSON字符串
     */
    public static String serialize(Map<String, Object> obj) {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();

        try (JsonGenerator jsonGenerator = jsonFactory.createGenerator(byteArrayOutputStream, JsonEncoding.UTF8)) {

            jsonGenerator.useDefaultPrettyPrinter();

            jsonGenerator.writeStartObject();
            jsonGenerator.writeNumberField("id", (int) obj.get("id"));
            jsonGenerator.writeStringField("str", (String) obj.get("str"));
            jsonGenerator.writeEndObject();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return byteArrayOutputStream.toString();
    }


    // jsonStr to Object
    private static Object deserializeJSONByStr(String jsonString) {
        JsonParser jsonParser = null;

        Object object = new Object(); // 可以声明自己想要的对象类型 然后返回 就是转换成指定类型

        try {
            jsonParser = jsonFactory.createParser(jsonString);

            if (jsonParser.nextToken() != JsonToken.START_OBJECT) {
                jsonParser.close();
                throw new IOException("起始位置没有大括号{");
            }

            while (jsonParser.nextToken() != JsonToken.END_OBJECT) {

                String fieldName = jsonParser.getCurrentName(); // 当前正在解析字段
                jsonParser.nextToken(); // * next 解析下一个


                /**
                 * 可以获取多种类型
                 * jsonParser.getLongValue()
                 * jsonParser.getText()
                 * jsonParser.getIntValue()
                 * jsonParser.getBooleanValue()
                 */
                String fieldValue = jsonParser.getValueAsString();

                System.out.println(fieldName + "->" + fieldValue);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return object;
    }

}

常用相关API

package com.study.other;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.*;

public class JacksonAPIDemo {
    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();

        TestVO testVO = new TestVO();
        testVO.setId(1);
        testVO.setAaa("aaa");
        testVO.setBbb(new Date());

        TestVO testVO2 = new TestVO();
        testVO2.setId(2);
        testVO2.setAaa("bbb");
        testVO2.setBbb(new Date());

        String jsonStr = mapper.writeValueAsString(testVO);
        System.out.println("对象序列化成字符串-->" + jsonStr);

        String testVOJsonStr = "{\"id\":2," +
                "\"aaa\":\"bbb\"," +
                "\"bbb\":1655513110837}";

        // 字符串 -> 对象
        TestVO testVOR1 = mapper.readValue(jsonStr, TestVO.class);
        System.out.println("反序列化--->" + testVOR1);

        // 对象 -> 文件
//        mapper.writeValue(new File("testVO.json"), testVOR1);
        // 文件 -> 对象
//        TestVO testVO2 = mapper.readValue(new File("testVO.json"), TestVO.class);
//        System.out.println(testVO2);

        // 对象 -> byte数组
//        byte[] array = mapper.writeValueAsBytes(testVOR1);
//        System.out.println("111->" + Arrays.toString(array));

        // byte数组 -> 对象
//        TestVO testVO3 = mapper.readValue(array, TestVO.class);
        // 字符串网络地址 -> 对象
//        mapper.readValue(new URL(jsonDataUrl), TestVO.class);


        System.out.println("-------------------------------------------------集合序列化相关API----------------------------------------------------");

        Map<String, Object> root = new HashMap<>(8);
        root.put("id", 1);
        root.put("aaa", "s1");

        Map<String, String> child = new HashMap<>();
        child.put("a","a");
        child.put("b", "b");

        root.put("child", child);

        String mapTestJsonStr = mapper.writeValueAsString(root);
        System.out.println("HashMap序列化的字符串---->" + mapTestJsonStr);

        Map<String, Object> mapFromStr = mapper.readValue(mapTestJsonStr, new TypeReference<Map<String, Object>>() {});
        System.out.println("HashMap反序列化---->" + mapFromStr);

        // JsonNode类型操作
        JsonNode jsonNode = mapper.readTree(mapTestJsonStr);
        System.out.println(jsonNode.get("child").get("a").asText());


        List<TestVO> list = new ArrayList<>(2);
        list.add(testVO);
        list.add(testVO2);

        String listStr = mapper.writeValueAsString(list);

        System.out.println("listStr->" + listStr);

        // json数组 -> 对象数组
        TestVO[] testVOArray = mapper.readValue(listStr, TestVO[].class);
        System.out.println("testVOArray--->" + Arrays.toString(testVOArray));

        // json数组 -> 对象集合
        List<TestVO> testVOList = mapper.readValue(listStr, new TypeReference<List<TestVO>>() {});
        System.out.println("testVOList--->" + testVOList);
    }
}


平时可能用到的自定义配置项说明:
1.反序列化时,遇到未知属性不要抛出异常:
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

2.空对象不要抛出异常:
mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);

3反序列化时,空字符串对于的实例属性为null:
mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);

4.序列化结果格式化:
mapper.enable(SerializationFeature.INDENT_OUTPUT);

5.Date、Calendar等序列化为时间格式的字符串(如果不执行以下设置,就会序列化成时间戳格式):
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);

6.允许C和C++样式注释:
mapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);

7.允许字段名没有引号(可以进一步减小json体积):
mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);

8.允许单引号:
mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);

9. 配合@JsonRootName(value = "xxx")注解使用 外层增加JSON嵌套注解
mapper.enable(SerializationFeature.WRAP_ROOT_VALUE); // 用于序列化 没有JsonRootName注解 有默认值Order1
mapper.enable(SerializationFeature.UNWRAP_ROOT_VALUE); // 用于反序列化 反序列化必须JsonRootName必须存在

实际工作相关

package com.study.other;

import com.fasterxml.jackson.annotation.JsonFilter;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.BeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.FilterProvider;
import com.fasterxml.jackson.databind.ser.PropertyFilter;
import com.fasterxml.jackson.databind.ser.PropertyWriter;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;

import java.util.*;

public class JacksonWorkTest {
    static class DTO {
        private int id;
        private String aaa;
        private String bbb;
        private DTO1 ccc;

        public int getId() {
            return id;
        }

        public void setId(int id) {
            this.id = id;
        }

        public String getAaa() {
            return aaa;
        }

        public void setAaa(String aaa) {
            this.aaa = aaa;
        }

        public String getBbb() {
            return bbb;
        }

        public void setBbb(String bbb) {
            this.bbb = bbb;
        }

        public DTO1 getCcc() {
            return ccc;
        }

        public void setCcc(DTO1 ccc) {
            this.ccc = ccc;
        }

        @Override
        public String toString() {
            return "DTO{" +
                    "id=" + id +
                    ", aaa='" + aaa + '\'' +
                    ", bbb='" + bbb + '\'' +
                    ", ccc='" + ccc + '\'' +
                    '}';
        }
    }

    static class DTO1 {
        private int id1;
        private String aaa1;
        private String bbb1;

        public int getId1() {
            return id1;
        }

        public void setId1(int id1) {
            this.id1 = id1;
        }

        public String getAaa1() {
            return aaa1;
        }

        public void setAaa1(String aaa1) {
            this.aaa1 = aaa1;
        }

        public String getBbb1() {
            return bbb1;
        }

        public void setBbb1(String bbb1) {
            this.bbb1 = bbb1;
        }

        @Override
        public String toString() {
            return "DTO1{" +
                    "id1=" + id1 +
                    ", aaa1='" + aaa1 + '\'' +
                    ", bbb1='" + bbb1 + '\'' +
                    '}';
        }
    }

    @JsonFilter("JsonFilterUtilByCm")
    static class JsonFilterUtilByCm extends FilterProvider {
        Map<Class<?>, Set<String>> includeMap = new HashMap<>();
        Map<Class<?>, Set<String>> filterMap = new HashMap<>();

        public void include(Class<?> type, String[] fields) {
            addToMap(includeMap, type, fields);
        }

        public void filter(Class<?> type, String[] fields) {
            addToMap(filterMap, type, fields);
        }

        private void addToMap(Map<Class<?>, Set<String>> map, Class<?> type, String[] fields) {
            Set<String> fieldSet = map.getOrDefault(type, new HashSet<>());
            fieldSet.addAll(Arrays.asList(fields));
            map.put(type, fieldSet);
        }

        @Override
        public BeanPropertyFilter findFilter(Object filterId) {
            throw new UnsupportedOperationException("Access to deprecated filters not supported");
        }

        @Override
        public PropertyFilter findPropertyFilter(Object filterId, Object valueToFilter) {
            return new SimpleBeanPropertyFilter() {
                @Override
                public void serializeAsField(Object pojo, JsonGenerator jsonGenerator, SerializerProvider provider, PropertyWriter writer)
                        throws Exception {
                    if (apply(pojo.getClass(), writer.getName())) {
                        writer.serializeAsField(pojo, jsonGenerator, provider);
                    } else if (!jsonGenerator.canOmitFields()) {
                        writer.serializeAsOmittedField(pojo, jsonGenerator, provider);
                    }
                }
            };
        }

        public boolean apply(Class<?> type, String name) {
            Set<String> includeFields = includeMap.get(type);
            Set<String> filterFields = filterMap.get(type);
            if (includeFields != null && includeFields.contains(name)) {
                return true;
            } else if (filterFields != null && !filterFields.contains(name)) {
                return true;
            } else if (includeFields == null && filterFields == null) {
                return true;
            }
            return false;
        }

    }


    // 测试实际工作中的序列化问题
    private static void test1() {
        ObjectMapper objectMapper = new ObjectMapper();
        DTO1 ccc = new DTO1();
        ccc.setId1(2);

        DTO dto = new DTO();
        dto.setId(1);
        dto.setBbb("bbb");
        dto.setCcc(ccc);

        JsonFilterUtilByCm jacksonFilterUtil = new JsonFilterUtilByCm();
        jacksonFilterUtil.include(dto.getClass(), new String[]{"id", "aaa", "ccc"});
        jacksonFilterUtil.include(ccc.getClass(), new String[]{"id", "aaa1"});
        objectMapper.setFilterProvider(jacksonFilterUtil);
        objectMapper.addMixIn(DTO.class, JsonFilterUtilByCm.class);
        objectMapper.addMixIn(DTO1.class, JsonFilterUtilByCm.class);
        try {
            System.out.println(objectMapper.writeValueAsString(dto));
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }


    // 测试实际工作中的反序列化问题
    private static void test2() {
        String str = "{\"id\":1,\"aaa\":null,\"ccc\":{\"aaa1\":null}}";
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            DTO obj = objectMapper.readValue(str, DTO.class);
            System.out.println(obj);
            System.out.println(obj.getAaa());
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
    }


    public static void main(String[] args) {
//        test1();
        test2();
    }
}

相关文章

网友评论

      本文标题:Jackson

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