使用Jackson解析json时,经常会需要获取到某一节点下的值,例如:
{
“data”: {
"test1": "value1",
"test2": null,
"test3": 10
}
}
以Jackson2.13.5为例,使用at(jsonPtrExp)这种API,解析json的代码并获取节点值的方法:
ObjectMapper objectMapper = new ObjectMapper();String content = "{"data": {\"test1\": \"value1\",\"test2\": null,\"test3\": 10}}";JsonNode root = objectMapper.readTree(content);JsonNode node = root.at("/data/test1");node.asText(); # 1
node.textValue(); # 2
这里有个让人疑惑的地方,获取其中的值时,到底应该用#1,还是用#2。
我们写一个测试用例,来看看它们的区别:
import java.io.IOException;import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;public class JacksonTester {public static void main(String[] args) throws IOException {ObjectMapper objectMapper = new ObjectMapper();String content = "{"data": {\"test1\": \"value1\",\"test2\": null,\"test3\": 10}}";JsonNode root = objectMapper.readTree(content);{JsonNode node = root.at("/data/test1");System.out.println("node.isMissingNode()##" + node.isMissingNode());System.out.println("node.isNull()##" + node.isNull());System.out.println("node.asText() == null##" + (node.asText() == null));System.out.println("node.asText()##" + node.asText());System.out.println("node.textValue() == null##" + (node.textValue() == null));System.out.println("node.textValue()##" + node.textValue());System.out.println("-------------");}{JsonNode node = root.at("/data/test2");System.out.println("node.isMissingNode()##" + node.isMissingNode());System.out.println("node.isNull()##" + node.isNull());System.out.println("node.asText() == null##" + (node.asText() == null));System.out.println("node.asText()##" + node.asText());System.out.println("node.textValue() == null##" + (node.textValue() == null));System.out.println("node.textValue()##" + node.textValue());System.out.println("-------------");}{JsonNode node = root.at("/data/test3");System.out.println("node.isMissingNode()##" + node.isMissingNode());System.out.println("node.isNull()##" + node.isNull());System.out.println("node.asText() == null##" + (node.asText() == null));System.out.println("node.asText()##" + node.asText());System.out.println("node.textValue() == null##" + (node.textValue() == null));System.out.println("node.textValue()##" + node.textValue());System.out.println("-------------");}{JsonNode node = root.at("/data/test4");System.out.println("node.isMissingNode()##" + node.isMissingNode());System.out.println("node.isNull()##" + node.isNull());System.out.println("node.asText() == null##" + (node.asText() == null));System.out.println("node.asText()##" + node.asText());System.out.println("node.textValue() == null##" + (node.textValue() == null));System.out.println("node.textValue()##" + node.textValue());System.out.println("-------------");}}}
执行结果:
node.isMissingNode()##false
node.isNull()##false
node.asText() == null##false
node.asText()##value1
node.textValue() == null##false
node.textValue()##value1
-------------
node.isMissingNode()##false
node.isNull()##true
node.asText() == null##false
node.asText()##null
node.textValue() == null##true
node.textValue()##null
-------------node.isMissingNode()##false
node.isNull()##true
node.asText() == null##false
node.asText()##10
node.textValue() == null##true
node.textValue()##null
-------------
node.isMissingNode()##true
node.isNull()##false
node.asText() == null##false
node.asText()##
node.textValue() == null##true
node.textValue()##null
-------------
从执行结果中可以看到
节点值为null时 | 节点不存在时 | 节点值为字符串时 | 节点值不为字符串时 | |
asText() | “null” | "" | "value1" | "10" |
textValue() | null | null | "value1" | null |
以下是JsonNode的子类及它们的层次结构
下面总结一下,当节点为上述类型并且值不为空时,asText()和textValue()获取到的值,以及正确获取值的方法
asText() | textValue() | 获取值的方法 | |
ArrayNode | "" | null | 使用elements()遍历 |
ObjectNode | "" | null | 使用elements()遍历 |
BinaryNode | 二进制的Base64编码后的值 | null | binaryValue() |
BooleanNode | "true" / "false" | null | booeanValue() |
MissingNode | "" | null | |
NullNode | "null" | null | 直接赋值为null |
NumberNode | 数字对应的字符串 | null | bigIntegerValue() decimal() doubleValue() intValue() longValue() |
POJONode | 内部包含的对象toString()返回值 | null | getPojo() |
TextNode | 字符串值 | 字符串值 | textValue() asText() |
综上,如果想要获取到各种类型节点实际的值,需要先将它转换成对应的类型,再使用对应类型的相应方法。
但如果只是想获取到ValueNode及其子类型节点的字符串值,只需要做如下判断后,直接使用asText()即可
if (!node.isMissingNode() && !node.isNull())
{String value = node.asText();
}
如果是使用textValue() ,只要节点值的类型是字符串,不用判断isMissingNode()和node.isNull(),就可以直接使用。