Jackson

基礎(chǔ)

1.jackson的github地址:https://github.com/FasterXML/jackson
2.jackson共有1.x和2.x兩個(gè)版本系列, 其中1.x已廢棄不再有版本發(fā)布, 2.x是活躍版本, 1.x和2.x并不兼容但也不沖突可以同時(shí)使用    
3.jackson有三個(gè)核心模塊
    jackson-core -> 低階API庫,提供流式解析工具JsonParser,流式生成工具JsonGenerator
    jackson-annotations -> jackson注解
    jackson-databind -> 基于java對象的序列化, 反序列化能力, 需要前面兩個(gè)模塊的支持才能實(shí)現(xiàn)

<!-- 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 已經(jīng)自動集成 如果是Spring 項(xiàng)目根本不需要引依賴

jackson-core 相關(guān)知識

相關(guān)核心API
    private static JsonFactory jsonFactory = new JsonFactory(); // 線程安全的 可以全局公用一個(gè)

    /**
     * jsonStr to Object
     * 反序列化測試(JSON STR -> Object),入?yún)⑹荍SON字符串
     */
    private static Object deserializeJSONByStr(String jsonString) {
        JsonParser jsonParser = null;

        Object object = new Object(); // 可以聲明自己想要的對象類型 然后返回 就是轉(zhuǎn)換成指定類型

        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(); // 當(dāng)前正在解析字段
                jsonParser.nextToken(); // * next 解析下一個(gè)


                /**
                 * 可以獲取多種類型
                 * 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(); // 可以聲明自己想要的對象類型 然后返回 就是轉(zhuǎn)換成指定類型

        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(); // 當(dāng)前正在解析字段
                jsonParser.nextToken(); // * next 解析下一個(gè)


                /**
                 * 可以獲取多種類型
                 * jsonParser.getLongValue()
                 * jsonParser.getText()
                 * jsonParser.getIntValue()
                 * jsonParser.getBooleanValue()
                 */
                String fieldValue = jsonParser.getValueAsString();

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

}

常用相關(guān)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數(shù)組
//        byte[] array = mapper.writeValueAsBytes(testVOR1);
//        System.out.println("111->" + Arrays.toString(array));

        // byte數(shù)組 -> 對象
//        TestVO testVO3 = mapper.readValue(array, TestVO.class);
        // 字符串網(wǎng)絡(luò)地址 -> 對象
//        mapper.readValue(new URL(jsonDataUrl), TestVO.class);


        System.out.println("-------------------------------------------------集合序列化相關(guān)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數(shù)組 -> 對象數(shù)組
        TestVO[] testVOArray = mapper.readValue(listStr, TestVO[].class);
        System.out.println("testVOArray--->" + Arrays.toString(testVOArray));

        // json數(shù)組 -> 對象集合
        List<TestVO> testVOList = mapper.readValue(listStr, new TypeReference<List<TestVO>>() {});
        System.out.println("testVOList--->" + testVOList);
    }
}


平時(shí)可能用到的自定義配置項(xiàng)說明:
1.反序列化時(shí),遇到未知屬性不要拋出異常:
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);

2.空對象不要拋出異常:
mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);

3反序列化時(shí),空字符串對于的實(shí)例屬性為null:
mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);

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

5.Date、Calendar等序列化為時(shí)間格式的字符串(如果不執(zhí)行以下設(shè)置,就會序列化成時(shí)間戳格式):
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);

6.允許C和C++樣式注釋:
mapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);

7.允許字段名沒有引號(可以進(jìn)一步減小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注解 有默認(rèn)值Order1
mapper.enable(SerializationFeature.UNWRAP_ROOT_VALUE); // 用于反序列化 反序列化必須JsonRootName必須存在

實(shí)際工作相關(guān)

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;
        }

    }


    // 測試實(shí)際工作中的序列化問題
    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();
        }
    }


    // 測試實(shí)際工作中的反序列化問題
    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();
    }
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容