在Java中,针对JSON也有标准的 JSR 353 (JSON Processing) API,
如果能直接在XML和JavaBean之间互相转换是最好的。常用的用于解析JSON的第三方库有:
什么是 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>
附录