Jackson中的JsonNode,ObjectNode,ArrayNode使用和区别
一、前言
若你的项目里使用Jackson处理JSON,必然会看到很多JsonNode、ObjectNode和ArrayNode的使用。
如果对它们概念很混淆,写代码时总是Ctrl+C别人的代码,那永远不会进步。
1. JsonNode作用
JsonNode是Jackson中为了处理JOSN文本的树模型(tree model)。可以将JSON文本转成JsonNode,也可以将JsonNode转成JOSN文本。JsonNode是只读的,不可修改,用它可以方便的获取JSON中某字段的值。
2. JsonNode VS ObjectNode
ObjectNode和ArrayNode都是JsonNode类的扩展,不同的是JsonNode是只读的,而ObjectNode和ArrayNode是可以修改的。如果只是从JSON文本中读取数据,用JsonNode就够了。
ObjectNode是一个JSON对象节点,ArrayNode就是一个数组,可以包含多个ObjectNode。
二、只读的JsonNode
1. 测试用的JSON文本
{
"id":"09194567",
"studentName":"王三",
"nickName": null,
"englishName":"King Three",
"age":32,
"email":"123@qq.com",
"birthday":"1989-12-21",
"joinDate":"2019-03-10 11:15:39",
"courseScores":[
{
"course":"Java",
"score":95
},
{
"course":"C#",
"score":94
},
{
"course":"C++",
"score":89
}
],
"courseScoresGroup":{
"A":[
"Java",
"C#"
],
"B":[
"C++"
]
},
"valid":true
}
2. JSON 和 JsonNode 相互转换
使用ObjectMapper 的readTree方法可以轻松将JSON转JsonNode。
FileReader fileReader = new FileReader(OBJECT_FILE_PATH);
String studentStr = fileReader.readString();
ObjectMapper mapper = new ObjectMapper();
JsonNode rootNode = mapper.readTree(studentStr);
JsonNode 转 JSON:
String json = mapper.writeValueAsString(rootNode);
JsonNode 转 Java对象:
Student student = mapper.treeToValue(rootNode, Student.class);
3. 使用get方法取值
get方法定义如下:
public JsonNode get(String fieldName)
get方法也是返回一个JsonNode。
- 如果 fieldName是在JSON中不存在的字段,则直接返回null。
- 如果字段的值本来就是null,比如"nickName",那么会返回一个NullNode,这个NullNode的textValue()就是"null"。
log.info("get(\"不存在的字段\") = " + rootNode.get("不存在的字段"));
log.info("get(\"studentName\") = " + rootNode.get("studentName"));
log.info("get(\"nickName\") = " + rootNode.get("nickName").textValue());
log.info("get(\"age\").intValue() = " + rootNode.get("age").intValue());
log.info("get(\"age\").textValue() = " + rootNode.get("age").textValue());
log.info("get(\"joinDate\") = " + rootNode.get("joinDate"));
log.info("get(\"valid\") = " + rootNode.get("valid"));
log.info("get(\"courseScores\") = " + rootNode.get("courseScores"));
log.info("get(\"courseScoresGroup\") = " + rootNode.get("courseScoresGroup"));
打印结果:
get("不存在的字段") = null
get("studentName") = "王三"
get("nickName") = null
get("age").intValue() = 32
get("age").textValue() = null
get("joinDate") = "2019-03-10 11:15:39"
get("valid") = true
get("courseScores") = [{"course":"Java","score":95},{"course":"C#","score":94},{"course":"C++","score":89}]
get("courseScoresGroup") = {"A":["Java","C#"],"B":["C++"]}
4. 使用path方法取值
path方法和get方法类似,但是如果取一个不存在的字段的值,返回的是MissingNode对象,它可以调用textValue(),这样的好处可以避免一些空指针问题,所以一定要注意get和path的区别。
log.info("path(\"不存在的字段\") = " + rootNode.path("不存在的字段"));
log.info("path(\"不存在的字段\").textValue() = " + rootNode.path("不存在的字段").textValue());
log.info("path(\"studentName\") = " + rootNode.path("studentName"));
log.info("path(\"nickName\") = " + rootNode.path("nickName"));
log.info("path(\"age\") = " + rootNode.path("age"));
log.info("path(\"courseScores\") = " + rootNode.path("courseScores"));
log.info("path(\"courseScoresGroup\") = " + rootNode.path("courseScoresGroup"));
打印结果:
path("不存在的字段") =
path("不存在的字段").textValue() = null
path("studentName") = "王三"
path("nickName") = null
path("age") = 32
path("courseScores") = [{"course":"Java","score":95},{"course":"C#","score":94},{"course":"C++","score":89}]
path("courseScoresGroup") = {"A":["Java","C#"],"B":["C++"]}
5. 使用at方法取值
因为JSON是有层级的数据格式,可以用at方法指定字段的路径,获取下面层级的字段。
如果指定了一个不存在的路径,返回的是MissingNode对象,这个特点和path相同。
log.info("at(\"studentName\") = " + rootNode.at("/studentName"));
JsonNode at1 = rootNode.at("/courseScoresGroup/A");
JsonNode at2 = rootNode.at("/courseScoresGroup/E");
log.info("at(\"/courseScoresGroup/A\") = " + at1);
log.info("at(\"/courseScoresGroup/E\") = " + at2);
log.info("at(\"/courseScoresGroup/E\").textValue() = " + at2.textValue());
打印结果:
at("studentName") = "王三"
at("/courseScoresGroup/A") = ["Java","C#"]
at("/courseScoresGroup/E") =
at("/courseScoresGroup/E").textValue() = null
三、可修改的ObjectNode
用ObjectNode可以自己构建JSON的内容,然后把ObjectNode转成JSON文本。
ObjectMapper mapper = new ObjectMapper();
ObjectNode studentNode = mapper.createObjectNode();
studentNode.put("id", "1");
studentNode.put("name", "亚瑟");
studentNode.put("age", 30);
//添加一个数组
List<CourseScore> courseScores = new ArrayList<>();
courseScores.add(new CourseScore("Java", 100));
courseScores.add(new CourseScore("C++", 90));
studentNode.put("courseScores", courseScores.toString());
System.out.println(studentNode.toPrettyString());
//删除一个属性
studentNode.remove("name");
System.out.println(studentNode.toPrettyString());
四、可修改的ArrayNode
如果属性的值是数组,你不需要对其修改时,直接用JsonNode 就行,isArray()判断是否是数组。
JsonNode courseScores = rootNode.get("courseScores");
if (courseScores.isArray() && !courseScores.isEmpty()) {
Iterator<JsonNode> elements = courseScores.elements();
while (elements.hasNext()) {
JsonNode score = elements.next();
System.out.println(score.toString());
}
}
结果如下:
{"course":"Java","score":95}
{"course":"C#","score":94}
{"course":"C++","score":89}
如果需要对值进行修改编辑,就得用ArrayNode 。
//创建一个pythonNode
ObjectNode pythonNode = mapper.createObjectNode();
pythonNode.put("course", "python");
pythonNode.put("score", 100);
ArrayNode arrayNode = (ArrayNode)rootNode.get("courseScores");
if (arrayNode.isArray() && !arrayNode.isEmpty()) {
//删除第一个Java
arrayNode.remove(0);
//又添加了一个python
arrayNode.add(pythonNode);
Iterator<JsonNode> elements = arrayNode.elements();
while (elements.hasNext()) {
JsonNode score = elements.next();
System.out.println(score.toString());
}
}
结果如下:
{"course":"C#","score":94}
{"course":"C++","score":89}
{"course":"python","score":100}