目录

Jackson JSON 解析库

在Java中,针对JSON也有标准的 JSR 353 (JSON Processing) API, 如果能直接在XML和JavaBean之间互相转换是最好的。常用的用于解析JSON的第三方库有:

  • Jackson
  • Gson
  • Fastjson

什么是 Jackson?

Jackson 被称为“Java JSON 库”或“Java 的最佳 JSON 解析器”。或者简单地称为“Java 的 JSON”。

不仅如此,Jackson 还是一套用于 Java(和 JVM 平台)的数据处理工具,包括旗舰流式JSON解析器/生成器库、匹配数据绑定库(POJO 与 JSON 之间的关系)和额外的数据格式模块处理以 Avro、 BSON、 CBOR、 CSV、 Smile、 (Java) Properties、 Protobuf、 TOML、 XML 或YAML编码的数据;甚至是庞大的数据格式模块集,以支持Guava、 Joda、 PCollections等广泛使用的数据类型的数据类型 还有很多很多。

而实际的核心组件存在于他们自己的项目下——包括三个核心包(流、数据绑定、注释);数据格式库;数据类型库;JAX-RS 提供者;和一组其他扩展模块——这个项目充当将所有部分连接在一起的中心枢纽。

核心模块

Core modules are the foundation on which extensions (modules) build upon. There are 3 such modules currently (as of Jackson 2.x):

  • Streaming (docs) (“jackson-core”) defines low-level streaming API, and includes JSON-specific implementations
  • Annotations (docs) (“jackson-annotations”) contains standard Jackson annotations
  • Databind (docs) (“jackson-databind”) implements data-binding (and object serialization) support on streaming package; it depends both on streaming and annotations packages
1
2
// https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.2.2'
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
public class ReadWriteJackson {
  public static void main(String[] args) throws IOException {
    ObjectMapper mapper = new ObjectMapper();
    // 反序列化时忽略不存在的JavaBean属性:
    mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
   
    String jsonInput = "{\"id\":0,\"firstName\":\"Robin\",\"lastName\":\"Wilson\"}";
    Person q = mapper.readValue(jsonInput, Person.class);
    System.out.println("Read and parsed Person from JSON: " + q);
   
    Person p = new Person("Roger", "Rabbit");
    String json = mapper.writeValueAsString(p);
    System.out.print(json);
    System.out.print("Person object " + p + " as JSON = ");
    mapper.writeValue(System.out, p);
  }
}

Jackson Annotation 例子

序列化注解

@JsonGetter 注解是 @JsonProperty 注解的替代品,它将方法标记为getter 方法。 当 json 字段与 JavaBean 字段不一致时,可以指定对应关系。

@JsonPropertyOrder 指定序列化顺序

@JsonRawValue 注释可以指示 Jackson 完全按原样序列化属性。

1
2
3
4
5
6
public class RawBean {
    public String name;

    @JsonRawValue
    public String json;
}
1
2
3
4
5
6
{
    "name":"My bean",
    "json":{
        "attr":false
    }
}

@JsonValue 序列化整个实例的单个方法。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
@Getter
@AllArgsConstructor
public enum GenderEnum {
  MALE(0, "Male"),
  FEMALE(1, "Female"),
  ;

  @JsonValue
  private final Integer value;
  private final String label;
}

@JsonSerialize 指定使用的自定义序列化程序。

反序列化注解

@JsonCreator 标注反序列化中使用的构造函数/工厂

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class BeanWithCreator {
    public int id;
    public String name;

    @JsonCreator
    public BeanWithCreator(
      @JsonProperty("id") int id, 
      @JsonProperty("theName") String name) {
        this.id = id;
        this.name = name;
    }
}

@Test
public void whenDeserializingUsingJsonCreator_thenCorrect()
  throws IOException {
 
    String json = "{\"id\":1,\"theName\":\"My bean\"}";

    BeanWithCreator bean = new ObjectMapper()
      .readerFor(BeanWithCreator.class)
      .readValue(json);
    assertEquals("My bean", bean.name);
}

@JsonSetter 是 @JsonProperty 的替代方法,将方法标记为 setter 方法。 需要读取一些 JSON 数据但目标实体类与该数据不完全匹配时使用。

1
2
3
4
5
6
7
8
9
public class MyBean {
    public int id;
    private String name;

    @JsonSetter("the_name")
    public void setName(String name) {
        this.name = name;
    }
}

@JsonDeserialize 表示使用自定义反序列化器。

@JsonAlias 在反序列化期间为属性定义一个或多个替代名称。

1
2
3
4
5
public class AliasBean {
    @JsonAlias({ "fName", "f_name" })
    private String firstName;   
    private String lastName;
}

反序列化 JSON Array

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
@Test
public void givenJsonArray_whenDeserializingAsArray_thenCorrect() 
  throws JsonParseException, JsonMappingException, IOException {
 
    ObjectMapper mapper = new ObjectMapper();
    List<MyDto> listOfDtos = Lists.newArrayList(
      new MyDto("a", 1, true), new MyDto("bc", 3, false));
    String jsonArray = mapper.writeValueAsString(listOfDtos);
 
    // [{"stringValue":"a","intValue":1,"booleanValue":true},
    // {"stringValue":"bc","intValue":3,"booleanValue":false}]

    MyDto[] asArray = mapper.readValue(jsonArray, MyDto[].class);
    assertThat(asArray[0], instanceOf(MyDto.class));
}

@Test
public void givenJsonArray_whenDeserializingAsListWithTypeReferenceHelp_thenCorrect() 
  throws JsonParseException, JsonMappingException, IOException {
 
    ObjectMapper mapper = new ObjectMapper();

    List<MyDto> listOfDtos = Lists.newArrayList(
      new MyDto("a", 1, true), new MyDto("bc", 3, false));
    String jsonArray = mapper.writeValueAsString(listOfDtos);

    List<MyDto> asList = mapper.readValue(
      jsonArray, new TypeReference<List<MyDto>>() { });
    assertThat(asList.get(0), instanceOf(MyDto.class));
}

@Test
public void givenJsonArray_whenDeserializingAsListWithJavaTypeHelp_thenCorrect() 
  throws JsonParseException, JsonMappingException, IOException {
    ObjectMapper mapper = new ObjectMapper();

    List<MyDto> listOfDtos = Lists.newArrayList(
      new MyDto("a", 1, true), new MyDto("bc", 3, false));
    String jsonArray = mapper.writeValueAsString(listOfDtos);

    CollectionType javaType = mapper.getTypeFactory()
      .constructCollectionType(List.class, MyDto.class);
    List<MyDto> asList = mapper.readValue(jsonArray, javaType);
 
    assertThat(asList.get(0), instanceOf(MyDto.class));
}

// 反序列化 Map
String jsonInput = "{\"key\": \"value\"}";
TypeReference<HashMap<String, String>> typeRef 
  = new TypeReference<HashMap<String, String>>() {};
Map<String, String> map = mapper.readValue(jsonInput, typeRef);

处理 Java 8 Date & Time

引入标准的 JSR310 关于 Java 8 Date & Time API 的数据格式。

1
2
// https://mvnrepository.com/artifact/com.fasterxml.jackson.datatype/jackson-datatype-jsr310
implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.2'
1
ObjectMapper mapper = new ObjectMapper().registerModule(new JavaTimeModule());

自定义

内置的解析规则和扩展的解析规则如果都不满足我们的需求,还可以自定义解析。

  • JsonSerializer<T>
  • JsonDeserializer<T>

附录