java系列 - fastjson, jackjson, Gson三者异同

java系列 - fastjson, jackjson, Gson三者异同,第1张

起源

当后端接口向前端返回数据时,有时response数据是null, 十分不利于前端处理。

因此为了统一格式,需要返回在:

  • 接口返回得数据是String类型时,不返回null,而返回 “”
  • 接口返回得数据是Map类型时,不返回null,而返回 {}
  • 接口返回得数据是List类型时,不返回null,而返回 []

为了解决这个问题,就到了选择json序列化工具得时候,目前有三种工具:

  • fastjson 是阿里巴巴2011年的开源 json 解析库
  • jackjson 是 spring boot 官方内置得 json 解析库
  • Gson 是 Google 官方2008年开源得 json 解析库
如何选择?

选择 jackson.( 2.13.0+版本)速度与性能安全,功能完善适中得选项。

如何使用?

添加坐标

<properties>
	......
    <jackson.version>2.13.2jackson.version>
    ......
properties>

dependencies>
	...
   
    <dependency>
        <groupId>com.fasterxml.jackson.coregroupId>
        <artifactId>jackson-databindartifactId>
        <version>${jackson.version}version>
    dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.coregroupId>
        <artifactId>jackson-annotationsartifactId>
        <version>${jackson.version}version>
    dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.coregroupId>
        <artifactId>jackson-coreartifactId>
        <version>${jackson.version}version>
    dependency>
    ...
dependencies>

全局配置文件:JacksonConfig.java

package com.springblog.config;


import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;

import java.io.IOException;
import java.lang.reflect.Field;
import java.util.Collection;

/**
 * 

* json序列化 *

* * @author [email protected] * @since 2022-05-09 */
@Configuration public class JacksonConfig { @Bean @Primary @ConditionalOnMissingBean(ObjectMapper.class) public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) { ObjectMapper objectMapper = builder.createXmlMapper(false).build(); objectMapper.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>() { @Override public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { String fieldName = jsonGenerator.getOutputContext().getCurrentName(); try { Field field = jsonGenerator.getCurrentValue().getClass().getDeclaredField(fieldName); if (CharSequence.class.isAssignableFrom(field.getType())) { // 字符串空值 “” jsonGenerator.writeString(""); } else if (Collection.class.isAssignableFrom(field.getType())) { //列表型空值返回[] jsonGenerator.writeStartArray(); jsonGenerator.writeEndArray(); } else { //map类型空值,或者bean对像,返回{} jsonGenerator.writeStartObject(); jsonGenerator.writeEndObject(); } } catch (NoSuchFieldException ignoredException) { // 忽略该异常 } } }); return objectMapper; } }
原理讲解

jackson有三个核心模块,如下,括号内是maven的artifactId:

  • Stre
  • aming(jackson-core):低阶API库,提供流式解析工具JsonParser,流式生成工具JsonGenerator;
  • Annotations(jackson-annotations):jackson注解;
  • Databind (jackson-databind):基于java对象的序列化、反序列化能力,需要前面两个模块的支持才能实现;

当我们用jackson做JSON *** 作时,常用的是 Databind 模块 的 ObjectMapper 类,对处于核心位置的jackson-core反倒是很少直接用到,那么该模块有什么作用呢?

jackson-core 中,有一个叫做 BeanSerializer 的功能类,其 serialize 方法负责 将java对象转为JSON字符串,方法中的处理逻辑就是调用JsonGenerator提供的API,而JsonGenerator就是jackson-core中负责序列化的主要功能类

日常使用序列化功能
  1. 将JSON转换为Java对象
  • 将json字符串序列化为Java对象
    public void jsonDemo() {
        String jsonString = "{ \"title\" : \"json博客标题\", \"description\" : \"json文章描述\" }";
        
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            BlogEntity blog = objectMapper.readValue(jsonString, BlogEntity.class);

            System.out.println("car brand = " + blog.getTitle());
            System.out.println("car doors = " + blog.getDescription());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

jackjson支持从各种类型数据中进行序列化为java对象,支持类型如下:

  • json字符串
ObjectMapper objectMapper = new ObjectMapper();
String json =
        "{ \"title\" : \"标题\", \"description\" :\"描述\" }";
Car car = objectMapper.readValue(json, BlogEntity.class);
  • 文件file
ObjectMapper objectMapper = new ObjectMapper();
File file = new File("data/blog.json");
BlogEntity blog = objectMapper.readValue(file, BlogEntity.class);
  • 字符输入流StringReader
ObjectMapper objectMapper = new ObjectMapper();
String json =
        "{ \"title\" : \"标题\", \"description\" :\"描述\" }";
Reader reader = new StringReader( json);
BlogEntity blog = objectMapper.readValue(file, BlogEntity.class);
  • JSON via URL
ObjectMapper objectMapper = new ObjectMapper();
URL url = new URL("file:data/blog.json");
BlogEntity blog = objectMapper.readValue(url, BlogEntity.class);
  • 字节输入流FileInputStream
ObjectMapper objectMapper = new ObjectMapper();
InputStream input = new FileInputStream("data/blog.json");
BlogEntity blog = objectMapper.readValue(input , BlogEntity.class);
  • 字节数组 List
ObjectMapper objectMapper = new ObjectMapper();
byte[] bytes =
        "{ \"title\" : \"标题\", \"description\" : \“描述\” }".getBytes("UTF-8");
BlogEntity blog = objectMapper.readValue(bytes , BlogEntity.class);
  • JSON数组字符串 :
ObjectMapper objectMapper = new ObjectMapper();
 String jsonArray = "[{\"title\":\"标题\"}, {\"description\":\"描述\"}]"
 // 转换为 Array
 BlogEntity[] blogs = objectMapper.readValue(jsonArray  , BlogEntity.class);

// 转换为List
 List<BlogEntity> blogs2 = objectMapper.readValue(jsonArray, new TypeReference<List<BlogEntity>>(){});
  • JSON字符串Map
ObjectMapper objectMapper = new ObjectMapper();
String jsonObject = "{\"brand\":\"ford\", \"doors\":5}";
Map<String, Object> jsonMap = objectMapper.readValue(jsonObject,
    new TypeReference<Map<String,Object>>(){});
  1. 将java对象转换为json字符串
 BlogEntity blogEntity = new BlogEntity();
 blogEntity.setTitle("新博客");
 blogEntity.setDescription("文章描述");
        
ObjectMapper objectMapper = new ObjectMapper();

String str = objectMapper.writeValueAsString(blogEntity);
System.out.println(str);
日常使用序列化注解
注解用法
@JsonProperty用于属性,把属性的名称序列化时转换为另外一个名称。示例:
@JsonProperty(“birth_date”)
private Date birthDate;
@JsonFormat用于属性或者方法,把属性的格式序列化时转换成指定的格式。示例:
@JsonFormat(timezone = “GMT+8”, pattern = “yyyy-MM-dd HH:mm”) )
public Date getBirthDate(){ }
@JsonPropertyOrder用于类, 指定属性在序列化时 json 中的顺序 , 示例:)
@JsonPropertyOrder({ “birth_Date”, “name” })
public class Person(){ }
@JsonCreator用于构造方法,和 @JsonProperty 配合使用,适用有参数的构造方法。 示例:
@JsonCreator
public Person(@JsonProperty(“name”) String name) {
  …
}
@JsonAnySetter用于属性或者方法,设置未反序列化的属性名和值作为键值存储到 map 中 )
@JsonAnySetter
public void set(String key, Object,value) {
   map.put(key, value);
}
@JsonAnyGetter用于方法 ,获取所有未序列化的属性 public Map any() { return map; }
参考资料

jackjson官方文档
jackjson方法细节
自定义解析

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/886323.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-14
下一篇 2022-05-14

发表评论

登录后才能评论

评论列表(0条)

保存