棄坑Fastjson ,進軍Jackson

Java學習社區

添加小編微信:372787553,備註進羣!

導語

Fastjson 是阿里開源的Json類庫,功能很強大,使用也很簡單,不得不說溫少還是很厲害的,但是fastjson卻經常會暴露出高危的漏洞,每次都是緊急發版,導致項目上經常會去更新,這一點讓使用者有點痛苦!

json的類庫還是很多的,比如:Gosn,JSON-B,Jackson,這三種json類庫也是Springboot官方推薦的,如圖:
在這裏插入圖片描述
但是這三者的使用,卻沒有Fastjson那麼方便,接下就進入我們今天的主角:Jackson

一. 簡介

​Jackson是一個簡單基於Java應用庫,Jackson可以輕鬆的將Java對象轉換成json對象和xml文檔,同樣也可以將json、xml轉換成Java對象。Jackson所依賴的jar包較少,簡單易用並且性能也要相對高些,並且Jackson社區相對比較活躍,更新速度也比較快。

1.1 特點

  • ​ 容易使用 - jackson API提供了一個高層次外觀,以簡化常用的用例。
  • ​ 無需創建映射 - API提供了默認的映射大部分對象序列化。
  • ​ 性能高 - 快速,低內存佔用,適合大型對象圖表或系統。
  • ​ 乾淨的JSON - jackson創建一個乾淨和緊湊的JSON結果,這是讓人很容易閱讀。
  • ​ 不依賴 - 庫不需要任何其他的庫,除了JDK。
  • ​ 開源代碼 - jackson是開源的,可以免費使用。

1.2 三種方式處理JSON

​ 提供了三種不同的方法來處理JSON

  • ​ 流式API - 讀取並將JSON內容寫入作爲離散事件。 JsonParser讀取數據,而JsonGenerator寫入數據。它是三者中最有效的方法,是最低的開銷和最快的讀/寫操作。它類似於Stax解析器XML。

  • ​ 樹模型 - 準備JSON文件在內存裏以樹形式表示。 ObjectMapper構建JsonNode節點樹。這是最靈活的方法。它類似於XML的DOM解析器。

  • ​ 數據綁定 - 轉換JSON並從POJO(普通Java對象)使用屬性訪問或使用註釋。它有兩個類型。

  • ​ 簡單的數據綁定 - 轉換JSON和Java Maps, Lists, Strings, Numbers, Booleans 和null 對象。

  • ​ 全部數據綁定 - 轉換爲JSON從任何JAVA類型。

​ ObjectMapper讀/寫JSON兩種類型的數據綁定。數據綁定是最方便的方式是類似XML的JAXB解析器。

二. 初識Jackson

ObjectMapper類是Jackson庫的主要類。它提供一些功能將轉換成Java對象匹配JSON結構,反之亦然。它使用JsonParser和JsonGenerator的實例實現JSON實際的讀/寫

2.1 第一個Jackson程序

本案例以Springboot項目爲例,Spring boot已經自帶了Jackson依賴,無需額外引用,接下類我們實現兩個常用的場景:Bean To Json , Json To Bean

  • Bean To Json
 	@Test
    public void beanToJson() throws JsonProcessingException {
        //創建mapper
        ObjectMapper mapper = new ObjectMapper();
        User user = new User("123", "123",13);
        //bean to json
        System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(user));

    }
  • Json To Bean
    @Test
    public void jsonToBean() throws JsonProcessingException {
        //創建mapper
        ObjectMapper mapper = new ObjectMapper();
        String jsonString = "{\"name\":\"haiji\", \"age\":21}";
        // json to bean
        System.out.println(mapper.readValue(jsonString, User.class));

    }
  • 運行結果
    在這裏插入圖片描述

三. 進階Jackson使用

在上面的案例中我們引進發現,每次使用時都需要創建一個ObjectMapper,而且使用起來也很多的冗餘代碼,這樣我們僅需要進一步優化,如下步驟:

  • 提供全局唯一的ObjectMapper
  • 封裝自定義的Jackson 工具

3.1 提供全局唯一的ObjectMapper

@Configuration
public class JacksonConfig {

    private final static Logger logger = LoggerFactory.getLogger(JacksonConfig.class);
    private static ObjectMapper objectMapper;
    private static Lock LOCK = new ReentrantLock(true);
    private static AtomicInteger TIME= new AtomicInteger(60);
    private final static Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();

    @Bean
    @Primary
    @ConditionalOnMissingBean(ObjectMapper.class)
    public static ObjectMapper jacksonObjectMapper() {
        if(ObjectUtils.isEmpty(objectMapper)){
            try {
                if(LOCK.tryLock(TIME.get(), TimeUnit.SECONDS) && ObjectUtils.isEmpty(objectMapper)){
                    objectMapper= builder.createXmlMapper(false).build();
                    // 通過該方法對mapper對象進行設置,所有序列化的對象都將按改規則進行系列化
                    // Include.Include.ALWAYS 默認
                    // Include.NON_DEFAULT 屬性爲默認值不序列化
                    // Include.NON_EMPTY 屬性爲 空("") 或者爲 NULL 都不序列化,則返回的json是沒有這個字段的。這樣對移動端會更省流量
                    // Include.NON_NULL 屬性爲NULL 不序列化
                    objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
                    objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
                    // 允許出現特殊字符和轉義符
                    objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);
                    // 允許出現單引號
                    objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
                    // 字段保留,將null值轉爲""
                    objectMapper.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>()
                    {
                        @Override
                        public void serialize(Object o, JsonGenerator jsonGenerator,
                                              SerializerProvider serializerProvider)
                                throws IOException
                        {
                            jsonGenerator.writeString("");
                        }
                    });
                }
            } catch (InterruptedException e) {
                logger.error("object mapper try lock ",e);
            }finally {
                LOCK.unlock();
            }
        }
        return objectMapper;
    }
}

3.2 封裝自定義的Jackson 工具

public class JsonUtils<T>{

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

   
    public static <T> T jsonToBean(@Nullable String string, Class<T> bean){
        assertNotNull("json to bean ", string);
        ObjectMapper objectMapper = JacksonConfig.jacksonObjectMapper();
        T t = null;
        try {
            t = objectMapper.readValue(string, bean);
        } catch (JsonProcessingException e) {
            logger.info("json to object is error -> JsonProcessingException ",e);
        }
        return t;
    }

   
    public static <T> String beanToJson(@Nullable T bean){
        assertNotNull("bean to json ",bean);
        ObjectMapper objectMapper = JacksonConfig.jacksonObjectMapper();
        String t = null;
        try {
            t =  objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(bean);
        } catch (JsonProcessingException e) {
            logger.info("json to object is error -> JsonProcessingException ",e);
        }
        return t;
    }

   
    public static <T> T jsonToBean(@Nullable String json, TypeReference<T> typeReference){
        assertNotNull("to json generics",json);
        ObjectMapper objectMapper = JacksonConfig.jacksonObjectMapper();
        T t = null;
        try {
            t = objectMapper.readValue(json, typeReference);
        } catch (IOException e) {
            logger.error("json to object is exception -> ",e);
        }
        return t;
    }

  
    public static <T> void beanToJson(@Nullable File file, T bean){
        assertNotNull("to file",file);
        ObjectMapper objectMapper = JacksonConfig.jacksonObjectMapper();
        try {
            objectMapper.writeValue(file,bean);
        } catch (IOException e) {
            logger.info("json to object is error -> IOException ",e);
        }
    }

  
    public static <T> T jsonToBean(@Nullable File file, TypeReference<T> typeReference){
        assertNotNull("to file",file);
        ObjectMapper objectMapper = JacksonConfig.jacksonObjectMapper();
        T t = null;
        try {
            t =  objectMapper.readValue(file,typeReference);
        } catch (IOException e) {
            logger.error("json to object exception -> ",e);
        }
        return t;
    }

   
    public static <T> JsonNode jsonToTree(@Nullable String json){
        assertNotNull("to tree",json);
        ObjectMapper objectMapper = JacksonConfig.jacksonObjectMapper();
        JsonNode jsonNode =null;
        try {
            jsonNode = objectMapper.readTree(json);
        } catch (JsonProcessingException e) {
            logger.error("json to tree exception ->",e);
        }
        return jsonNode;
    }


    public static <T> T jsonToBean(@Nullable URL url, Class<T> bean){
        assertNotNull("url",url);
        ObjectMapper objectMapper = JacksonConfig.jacksonObjectMapper();
        T t = null;
        try {
            t = objectMapper.readValue(url, bean);
        } catch (IOException e) {
            logger.info("url to object is error -> IOException ",e);
        }
        return t;
    }

   
    public static <T> T jsonToBean(@Nullable URL url, TypeReference<T> bean){
        assertNotNull("url generic paradigm",url);
        ObjectMapper objectMapper = JacksonConfig.jacksonObjectMapper();
        T t = null;
        try {
            t = objectMapper.readValue(url, bean);
        } catch (IOException e) {
            logger.info("url to object is error -> IOException ",e);
        }
        return t;
    }


  
    public static <T> T inputStreamToBean(@Nullable InputStream inputStream, Class<T> bean){
        assertNotNull("inputStream class",inputStream);
        ObjectMapper objectMapper = JacksonConfig.jacksonObjectMapper();
        T t = null;
        try {
            t = objectMapper.readValue(inputStream, bean);
        } catch (IOException e) {
            logger.info("url to object is error -> IOException ",e);
        }
        return t;
    }

    
    public static <T> T inputStreamToBean(@Nullable InputStream inputStream, TypeReference<T> bean){
        assertNotNull("inputStream",inputStream);
        ObjectMapper objectMapper = JacksonConfig.jacksonObjectMapper();
        T t = null;
        try {
            t = objectMapper.readValue(inputStream, bean);
        } catch (IOException e) {
            logger.info("url to object is error -> IOException ",e);
        }
        return t;
    }

    public static <T> T byteToBean(@Nullable byte[] src, Class<T> bean){
        assertNotNull("byte class",src);
        ObjectMapper objectMapper = JacksonConfig.jacksonObjectMapper();
        T t = null;
        try {
            t = objectMapper.readValue(src, bean);
        } catch (IOException e) {
            logger.info("url to object is error -> IOException ",e);
        }
        return t;
    }

    public static <T> T byteToBean(@Nullable byte[] src, TypeReference<T> bean){
        assertNotNull("byte TypeReference",src);
        ObjectMapper objectMapper = JacksonConfig.jacksonObjectMapper();
        T t = null;
        try {
            t = objectMapper.readValue(src, bean);
        } catch (IOException e) {
            logger.info("url to object is error -> IOException ",e);
        }
        return t;
    }


   
    protected static void assertNotNull(String paramName, Object src) {
        if (ObjectUtils.isEmpty(src)) {
            throw new IllegalArgumentException(String.format("argument \"%s\" is null", paramName));
        }
    }
}

3.3 使用驗證

    @Test
    public void testJson(){
        User user = new User("123", "123",13);
        System.out.println(JsonUtils.beanToJson(user));
        String jsonString = "[{\"name\":\"haiji\", \"age\":21},{\"name\":\"java\", \"age\":21}]";
        System.out.println(JsonUtils.jsonToBean(jsonString, new TypeReference<List<User>>() {}));

    }

在這裏插入圖片描述
這裏只是對常用的一些json工具進行了封裝,大家也可以自己進行

案例源代碼地址:https://github.com/yanghaiji/javayh-platform/tree/master/javayh-dependencies/javayh-common-starter/src/main/java/com/javayh/common

如果對你有幫助,請給個贊吧!

本文的分享暫時就到這裏,希望對您有所幫助
關注 Java有貨領取更多資料

聯繫小編。微信:372787553,帶您進羣互相學習
左側小編微信,右側獲取免費資料
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章