Java 中动态 JSON 对象的使用
最主流的 JSON 处理库是 fasterxml 的
Jaskson和 google 的Gson等。(其他的还有比如com.alibaba:fastjson或net.sf.json-lib:json-lib等)
在已有实体类结构的情况下,现有的 JSON 库可以轻松地把 JSON 文本反序列为实体类。
// Jackson 序列化
com.fasterxml.jackson.databind.ObjectMapper#writeValueAsString
// Jackson 反序列化
com.fasterxml.jackson.databind.ObjectMapper#readValue(java.lang.String, java.lang.Class<T>)
// Gson 序列化
com.google.gson.Gson#toJson(java.lang.Object)
// Gson 反序列化
com.google.gson.Gson#fromJson(java.lang.String, java.lang.Class<T>)
但是如果未知实体类的结构,那么一般操作方式就是直接把 JSON 文本转成java.util.Map,或者JSON 库本身的JSON对象模型。
一、Jackson
1. 基本模型
Jaskson的动态JSON对象模型如下图所示:

顶层是TreeNode和JsonNode,其可直接使用的子类主要分为两种,分别是ContainerNode和ValueNode:
- 其中
ValueNode的众多子类是 JSON 中的各种值类型,例如某个key的value是一个字符串(TextNode)、或者整型(IntNode)、或者null(NullNode)。或者一个单独的值也是符合 JSON 结构规范的。 - 而
ContainerNode则是最常见的 JSON 结构了,主要分为ObjectNode和ArrayNode,分别对应两个顶层结构:花括号({})与方括号([])。
使用方法:
- 使用
com.fasterxml.jackson.databind.ObjectMapper#readTree(java.lang.String)方法把 JSON 文本解析成JsonNode对象。当然这个方法还有其他重载可以接受不同参数,此处不再赘述。 - 使用
com.fasterxml.jackson.databind.node.JsonNodeFactory#*Node方法可以创建各种 Node 对象。ArrayNode/ObjectNode/ObjectMapper 也可以创建各种 Node 对象,是通过调用其内部的JsonNodeFactory实例完成的。
2. 示例
以如下的 JSON 文本举例:
[
{
"name": "zhangsan",
"age": 24
},
{
"name": "lisi",
"age": 30
}
]
先在项目的Gradle文件中导入依赖:
implementation 'com.fasterxml.jackson.core:jackson-databind:2.13.0-rc2'
引入
jackson-databind即可,jackson-databind会自己引入对应的jackson-core和jackson-annotations。
然后直接上代码片段:
import com.fasterxml.jackson.core.JsonProcessingException;
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.IntNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.TextNode;
public class JacksonTest {
/**
* <pre> json:
* [
* {
* "name": "zhangsan",
* "age": 24
* },
* {
* "name": "lisi",
* "age": 30
* }
* ]
* </pre>
*/
private static final String json = "[{\"name\": \"zhangsan\",\"age\": 24},{\"name\": \"lisi\",\"age\": 30}]";
private static ObjectMapper objectMapper = new ObjectMapper();
public static void main(String[] args) {
JsonNode jsonNode = null;
try {
// 把 JSON 文本解析成 JsonNode 对象
jsonNode = objectMapper.readTree(json);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
// 该 JSON 文本最顶层的 JSON 模型是一个 ArrayNode
ArrayNode arrayNode = (ArrayNode) jsonNode;
// ArrayNode 的第一项是一个 ObjectNode
ObjectNode objectNode = (ObjectNode) arrayNode.get(0);
// 该 objectNode 中 key 为 "name" 的值
TextNode name = (TextNode) objectNode.get("name");
// 该 objectNode 中 key 为 "age" 的值
IntNode age = (IntNode) objectNode.get("age");
// 往 ObjectNode 中添加键值对,或者修改 value
objectNode.put("city", "beijing");
objectNode.put("age", 25);
// 往 ArrayNode 中删除一项,或者添加一项
arrayNode.remove(1);
arrayNode.add("a new item");
// JsonNodeFactory.instance.*Node 方法可以创建各种 Node 对象
arrayNode.add(JsonNodeFactory.instance.nullNode());
// 直接 print 可以打印 JSON 文本
System.out.println(jsonNode);
// ArrayNode/ObjectNode/ObjectMapper 也可以创建各种 Node 对象
TextNode textNode1 = arrayNode.textNode("test");
ArrayNode arrayNode1 = objectMapper.createArrayNode();
System.out.println(textNode1);
}
}
参考:
https://www.baeldung.com/jackson-mapping-dynamic-object
https://www.baeldung.com/jackson-json-node-tree-model
二、Gson
1. 基本模型
相比Jackson,Gson的动态JSON对象模型就比较简洁:

- 顶层是
JsonElement,其可直接使用的子类主要分为四种:JsonObject、JsonArray、JsonNull、JsonPrimitive。前三个可以从字面理解,JsonPrimitive则是各种基本值类型,大概类似于 Jackson 的ValueNode除去NullNode。
注意
gson的com.google.gson.JsonObject与json-lib的net.sf.json.JSONObject和fastjson的com.alibaba.fastjson.JSONObject区分一下,不要用混了。
使用方法:
- 使用
com.google.gson.JsonParser#parseString方法把 JSON 文本解析成JsonElement对象。当然这个方法还有其他类似的比如parseReader,此处不再赘述。 JsonElement的各个子类都可以直接new出来,其中JsonNull则推荐使用JsonNull.INSTANCE。
2. 示例
依旧以上面的 JSON 文本举例,先在项目的Gradle文件中导入依赖:
implementation 'com.google.code.gson:gson:2.8.6'
然后直接上代码片段:
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive;
public class GsonTest {
/**
* <pre> json:
* [
* {
* "name": "zhangsan",
* "age": 24
* },
* {
* "name": "lisi",
* "age": 30
* }
* ]
* </pre>
*/
private static final String json = "[{\"name\": \"zhangsan\",\"age\": 24},{\"name\": \"lisi\",\"age\": 30}]";
public static void main(String[] args) {
// 把 JSON 文本解析成 JsonElement 对象
JsonElement jsonElement = JsonParser.parseString(json);
// 该 JSON 文本最顶层的 JSON 模型是一个 JsonArray
JsonArray jsonArray = (JsonArray) jsonElement;
// JsonArray 的第一项是一个 JsonObject
JsonObject jsonObject = (JsonObject) jsonArray.get(0);
// 该 JsonObject 中 key 为 "name" 的值
JsonPrimitive name = (JsonPrimitive) jsonObject.get("name");
// 该 JsonObject 中 key 为 "age" 的值
JsonPrimitive age = (JsonPrimitive) jsonObject.get("age");
// 往 JsonObject 中添加键值对,或者修改 value
jsonObject.addProperty("city", "beijing");
jsonObject.addProperty("age", 25);
// 往 JsonArray 中删除一项,或者添加一项
jsonArray.remove(1);
jsonArray.add("first new item");
// 各种 Json 模型对象可以直接 new 出来,null 则推荐 JsonNull.INSTANCE
jsonArray.add(new JsonPrimitive("second new item"));
// 直接 print 可以打印 JSON 文本
System.out.println(jsonElement);
}
}
三、总结
介绍了Jaskson和Gson的动态JSON对象的模型与基本使用方式,至于这两个 JSON 库基础的序列化与反序列化、或者动态JSON对象更进一步的使用方式 可以自己读一下二者的文档(Gson Jackson)。个人虽然平时用Jackson比较多,但是感觉Gson更加简洁。
TODO 有空更一篇 JsonPath 的介绍。

浙公网安备 33010602011771号