Len's Study-Log

集中一点,登峰造极!

0%

Jackson文档翻译-Tree Model examples.md

原文


在 Jackson 中,我们可以用 Tree Model 来表示 JSON 结构,然后通过 JsonNode 展示CRUD的操作,类似于 XML DOM 树。Jackson 的 Tree Model 非常有用,特别是在 JSON 结构不能很好地和 Java 类映射匹配的时候。
导入 Jackson 依赖包:

1
2
3
4
5
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.8</version>
</dependency>

1. 遍历 JSON

1.1 遍历 JSON 文件的 Jackson TreeModel 示例:
C:\projects\user.json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"id": 1,
"name": {
"first": "Yong",
"last": "Mook Kim"
},
"contact": [
{
"type": "phone/home",
"ref": "111-111-1234"
},
{
"type": "phone/work",
"ref": "222-222-2222"
}
]
}

1.2 一个个地处理JsonNode:
JacksonTreeModelExample1.java:

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
53
54
55
56
57
package com.mkyong;

import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.File;
import java.io.IOException;

public class JacksonTreeModelExample1 {

private static final ObjectMapper mapper = new ObjectMapper();

public static void main(String[] args) {

try {

JsonNode root = mapper.readTree(new File("c:\\projects\\user.json"));

// Get id
long id = root.path("id").asLong();
System.out.println("id : " + id);

// Get Name
JsonNode nameNode = root.path("name");
if (!nameNode.isMissingNode()) { // if "name" node is exist
System.out.println("firstName : " + nameNode.path("first").asText());
System.out.println("middleName : " + nameNode.path("middle").asText());
System.out.println("lastName : " + nameNode.path("last").asText());
}

// Get Contact
JsonNode contactNode = root.path("contact");
if (contactNode.isArray()) {

System.out.println("Is this node an Array? " + contactNode.isArray());

for (JsonNode node : contactNode) {
String type = node.path("type").asText();
String ref = node.path("ref").asText();
System.out.println("type : " + type);
System.out.println("ref : " + ref);

}
}

} catch (JsonGenerationException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

}

output:
1
2
3
4
5
6
7
8
9
10
11
id : 1

firstName : Yong
middleName :
lastName : Mook Kim

Is this node an Array? true
type : phone/home
ref : 111-111-1234
type : phone/work
ref : 222-222-2222

2. 遍历 JSON 数组

2.1 下面的 JSON 文件,顶层代表着一个数组

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
[
{
"id": 1,
"name": {
"first": "Yong",
"last": "Mook Kim"
},
"contact": [
{
"type": "phone/home",
"ref": "111-111-1234"
},
{
"type": "phone/work",
"ref": "222-222-2222"
}
]
},
{
"id": 2,
"name": {
"first": "Yong",
"last": "Zi Lap"
},
"contact": [
{
"type": "phone/home",
"ref": "333-333-1234"
},
{
"type": "phone/work",
"ref": "444-444-4444"
}
]
}
]

2.2 概念是一样的,只是循环一下 JSON 数组:

1
2
3
4
5
JsonNode rootArray = mapper.readTree(new File("c:\\projects\\user2.json"));

for (JsonNode root : rootArray) {
// get node like the above example 1
}

JacksonTreeModelExample2.java:
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
53
54
55
56
57
58
59
60
61
package com.mkyong;

import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.File;
import java.io.IOException;

public class JacksonTreeModelExample2 {

private static final ObjectMapper mapper = new ObjectMapper();

public static void main(String[] args) {

try {

JsonNode rootArray = mapper.readTree(new File("c:\\projects\\user2.json"));

for (JsonNode root : rootArray) {

// Get id
long id = root.path("id").asLong();
System.out.println("id : " + id);

// Get Name
JsonNode nameNode = root.path("name");
if (!nameNode.isMissingNode()) { // if "name" node is exist
System.out.println("firstName : " + nameNode.path("first").asText());
System.out.println("middleName : " + nameNode.path("middle").asText());
System.out.println("lastName : " + nameNode.path("last").asText());
}

// Get Contact
JsonNode contactNode = root.path("contact");
if (contactNode.isArray()) {

System.out.println("Is this node an Array? " + contactNode.isArray());

for (JsonNode node : contactNode) {
String type = node.path("type").asText();
String ref = node.path("ref").asText();
System.out.println("type : " + type);
System.out.println("ref : " + ref);

}
}

}

} catch (JsonGenerationException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

}

Output:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
id : 1
firstName : Yong
middleName :
lastName : Mook Kim
Is this node an Array? true
type : phone/home
ref : 111-111-1234
type : phone/work
ref : 222-222-2222

id : 2
firstName : Yong
middleName :
lastName : Zi Lap
Is this node an Array? true
type : phone/home
ref : 333-333-1234
type : phone/work
ref : 444-444-4444

3. Tree model CRUD example

3.1 这个例子,向你展示如何新增、更新和删除 JSON 节点。为了修改 JSON 节点,我们需要把它转换成 ObjectNode。阅读并理解下面的内容:

JacksonTreeModelExample3.java

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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
package com.mkyong;

import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;

import java.io.File;
import java.io.IOException;

public class JacksonTreeModelExample3 {

private static final ObjectMapper mapper = new ObjectMapper();

public static void main(String[] args) {

try {

JsonNode root = mapper.readTree(new File("c:\\projects\\user.json"));

String resultOriginal = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(root);
System.out.println("Before Update " + resultOriginal);

// 1. Update id to 1000
((ObjectNode) root).put("id", 1000L);

// 2. If middle name is empty , update to M
ObjectNode nameNode = (ObjectNode) root.path("name");
if ("".equals(nameNode.path("middle").asText())) {
nameNode.put("middle", "M");
}

// 3. Create a new field in nameNode
nameNode.put("nickname", "mkyong");

// 4. Remove last field in nameNode
nameNode.remove("last");

// 5. Create a new ObjectNode and add to root
ObjectNode positionNode = mapper.createObjectNode();
positionNode.put("name", "Developer");
positionNode.put("years", 10);
((ObjectNode) root).set("position", positionNode);

// 6. Create a new ArrayNode and add to root
ArrayNode gamesNode = mapper.createArrayNode();

ObjectNode game1 = mapper.createObjectNode().objectNode();
game1.put("name", "Fall Out 4");
game1.put("price", 49.9);

ObjectNode game2 = mapper.createObjectNode().objectNode();
game2.put("name", "Dark Soul 3");
game2.put("price", 59.9);

gamesNode.add(game1);
gamesNode.add(game2);
((ObjectNode) root).set("games", gamesNode);

// 7. Append a new Node to ArrayNode
ObjectNode email = mapper.createObjectNode();
email.put("type", "email");
email.put("ref", "abc@mkyong.com");

JsonNode contactNode = root.path("contact");
((ArrayNode) contactNode).add(email);

String resultUpdate = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(root);

System.out.println("After Update " + resultUpdate);

} catch (JsonGenerationException e) {
e.printStackTrace();
} catch (JsonMappingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

}

Output:

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
Before Update {
"id" : 1,
"name" : {
"first" : "Yong",
"last" : "Mook Kim"
},
"contact" : [ {
"type" : "phone/home",
"ref" : "111-111-1234"
}, {
"type" : "phone/work",
"ref" : "222-222-2222"
} ]
}

After Update {
"id" : 1000,
"name" : {
"first" : "Yong",
"middle" : "M",
"nickname" : "mkyong"
},
"contact" : [ {
"type" : "phone/home",
"ref" : "111-111-1234"
}, {
"type" : "phone/work",
"ref" : "222-222-2222"
}, {
"type" : "email",
"ref" : "abc@mkyong.com"
} ],
"position" : {
"name" : "Developer",
"years" : 10
},
"games" : [ {
"name" : "Fall Out 4",
"price" : 49.9
}, {
"name" : "Dark Soul 3",
"price" : 59.9
} ]
}