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" : "[email protected]" , "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" , "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}
简单来说 ObjectNodeArrayNodeJsonNode 的扩展,ObjectNodeArrayNode 是基于 JsonNode 的。
ArrayNode具有处理数组的特定方法。
更多的,因为 JsonNode 是不可变的,因此通常使用 JsonNode 来读取数据,ObjectNode 来写入数据。
				
package com.fasterxml.jackson.databind; import com.fasterxml.jackson.core.JsonPointer; import com.fasterxml.jackson.core.TreeNode; import com.fasterxml.jackson.databind.JsonSerializable.Base; import ...
private static JsonNodeFactory factory = new JsonNodeFactory(false); ObjectNode objectNode = factory.objectNode(); ObjectNode dataObjectNode = JsonNodeFactory.instance.objectNode();
介绍Jackson JsonNodeObjectNode Jackson JsonNode类,完整路径为com.fasterxml.jackson.databind.JsonNode,是Jacksonjson树模型(对象图模型)。Jackson能读JSONJsonNode实例,写JsonNodeJSON。本文不涉及json序列化或反序列化,主要介绍如何从头构建JsonNode对象图,之后你可以序列化为json。 1. JsonNode vs. ObjectNode The Jackson JsonN
[1]有很多图片放服务器里,怎么能更好的管理,更方便拿到图片呢? [2]想用json 以一个对象数组的形式保存这些图片:以[{img:"图片名"},{img:"图片名"}....]形式 [3]虽说想法是很好,但不可能一条一条自己写吧,好歹咱也是21世纪敲代码的人。 [4]刚好最...
JsonNodeJackson为了处理JOSN文本的树模型(tree model)。可以将JSON文本转成JsonNode,也可以将JsonNode转成JOSN文本。。 ObjectNodeArrayNode都是JsonNode类的扩展,不同的是JsonNode是只读的,而。...
– Start 除了 ObjectMapper 外,如果你不想创建和消息格式一样的对象模型,我们还可以使用 JsonNode 来访问 JSON 消息,下面是一个简单的例子。 package shangbo.jackson.demo19; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.dat...