添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

2.创建一个节点

创建节点的第一步是使用默认构造函数实例化ObjectMapper对象:

ObjectMapper mapper = new ObjectMapper();

由于创建ObjectMapper对象非常昂贵,因此建议将同一对象重复用于多个操作。

接下来,一旦有了ObjectMapper,就有三种不同的方式来创建树节点。

2.1 从头开始构建节点

创建节点的最常见方法如下:

JsonNode node = mapper.createObjectNode();

另外,也可以通过JsonNodeFactory创建一个节点:

JsonNode node = JsonNodeFactory.instance.objectNode();

2.2从JSON来源解析

之前文章《JSON字符串转换为JsonNode》

2.3从对象转换

可以通过在ObjectMapper上调用valueToTree(Object fromValue)方法来从Java对象转换节点:

JsonNode node = mapper.valueToTree(fromValue);

convertValue API在这里也很有帮助:

JsonNode node = mapper.convertValue(fromValue, JsonNode.class);

如何使用,创建NodeBean

@Data
@AllArgsConstructor
@NoArgsConstructor
public class NodeBean {
    private int id;
    private String name;

编写单元测试,确保转化正确

     NodeBean fromValue = new NodeBean(2016, "123456.com");
        ObjectMapper mapper = new ObjectMapper();
        JsonNode node = mapper.valueToTree(fromValue);
        assertEquals(2016, node.get("id").intValue());
        assertEquals("123456.com", node.get("name").textValue());

3.转换节点

3.1写为JSON

将树节点转换为JSON字符串的基本方法如下:

mapper.writeValue(destination, node);

其中目标可以是File,OutputStream或Writer。

public class ExampleStructure {
    private static ObjectMapper mapper = new ObjectMapper();
    public static JsonNode getExampleRoot() throws IOException {
        return mapper.createObjectNode();
String newString = "{\"nick\": \"cowtowncoder\"}";
ObjectMapper mapper = new ObjectMapper();
JsonNode newNode = mapper.readTree(newString);
JsonNode rootNode = ExampleStructure.getExampleRoot();
((ObjectNode) rootNode).set("name", newNode);
//{"name":{"nick":"cowtowncoder"}}
System.out.println(rootNode.toString());
assertFalse(rootNode.path("name").path("nick").isMissingNode());
assertEquals("cowtowncoder", rootNode.path("name").path("nick").textValue());

3.2转换为对象

将JsonNode转换为Java对象的最方便的方法是treeToValue API:

NodeBean toValue = mapper.treeToValue(node, NodeBean.class);

在功能上等效于:

NodeBean toValue = mapper.convertValue(node, NodeBean.class)

还可以通过令牌流来做到这一点:

JsonParser parser = mapper.treeAsTokens(node);
NodeBean toValue = mapper.readValue(parser, NodeBean.class);
ObjectMapper mapper = new ObjectMapper();
ObjectNode node = mapper.createObjectNode();
node.put("id", 2016);
node.put("name", "baeldung.com");
NodeBean toValue = mapper.treeToValue(node, NodeBean.class);
assertEquals(2016, toValue.getId());
assertEquals("baeldung.com", toValue.getName());

4.操纵树节点

json数据结构如下:

"name": "first": "Tatu", "last": "Saloranta" "title": "Jackson founder", "company": "FasterXML"

4.1定位节点

在任何节点上工作之前,要做的第一件事是找到并将其分配给变量。

如果事先知道节点的路径,那将很容易做到。 例如,想要一个名为last的节点,该节点位于名称node下:

JsonNode locatedNode = rootNode.path("name").path("last");
        String json = "{\"name\":{\"first\":\"Tatu\",\"last\":\"Saloranta\"},\"title\":\"Jackson founder\",\"company\":\"FasterXML\"}";
        ObjectMapper mapper = new ObjectMapper();
        JsonNode rootNode = mapper.readTree(json);
        JsonNode locatedNode = rootNode.path("name").path("last");
        System.out.println(locatedNode); //Saloranta

另外,也可以使用get或with API代替path。

4.2添加一个新节点

可以将一个节点添加为另一个节点的子节点,如下所示:

ObjectNode newNode = ((ObjectNode) locatedNode).put(fieldName, value);

put的许多重载变体可以用于添加不同值类型的新节点。

还可以使用许多其他类似方法,包括putArray,putObject,PutPOJO,putRawValue和putNull。

最后,让看一个示例,在该示例中,将整个结构添加到树的根节点:

"address":
    "city": "Seattle",
    "state": "Washington",
    "country": "United States"
String json = "{\"name\":{\"first\":\"Tatu\",\"last\":\"Saloranta\"},\"title\":\"Jackson founder\",\"company\":\"FasterXML\"}";
        ObjectMapper mapper = new ObjectMapper();
        JsonNode rootNode = mapper.readTree(json);
        ObjectNode addedNode = ((ObjectNode) rootNode).putObject("address");
        addedNode
                .put("city", "Seattle")
                .put("state", "Washington")
                .put("country", "United States");
        System.out.println(rootNode);
        //{"name":{"first":"Tatu","last":"Saloranta"},"title":"Jackson founder","company":"FasterXML","address":{"city":"Seattle","state":"Washington","country":"United States"}}

4.3编辑节点

可以通过调用set(String fieldName,JsonNode value)方法来修改ObjectNode实例:

JsonNode locatedNode = locatedNode.set(fieldName, value);

通过对相同类型的对象使用replace或setAll方法,可以得到类似的结果。

ObjectMapper mapper = new ObjectMapper();
String newString = "{\"nick\": \"cowtowncoder\"}";
JsonNode newNode = mapper.readTree(newString);
JsonNode rootNode = mapper.createObjectNode();
((ObjectNode) rootNode).set("name", newNode);
System.out.println(rootNode);//{"name":{"nick":"cowtowncoder"}}
System.out.println(rootNode.path("name").path("nick").isMissingNode()); //false
System.out.println(rootNode.path("name").path("nick").textValue());//cowtowncoder

4.4移除一个节点

可以通过在父节点上调用remove(String fieldName)API来删除该节点:

JsonNode removedNode = locatedNode.remove(fieldName);

为了一次删除多个节点,可以使用Collection 类型的参数调用一个重载方法,该方法将返回父节点而不是要删除的父节点:

ObjectNode locatedNode = locatedNode.remove(fieldNames);
   String json = "{\"name\":{\"first\":\"Tatu\",\"last\":\"Saloranta\"},\"title\":\"Jackson founder\",\"company\":\"FasterXML\"}";
        ObjectMapper mapper = new ObjectMapper();
        JsonNode rootNode = mapper.readTree(json);
        ((ObjectNode) rootNode).remove("company");
        System.out.println(rootNode.path("company").isMissingNode());//true
        System.out.println(rootNode); //{"name":{"first":"Tatu","last":"Saloranta"},"title":"Jackson founder"}

5.遍历节点

遍历JSON文档中的所有节点,并将它们重新格式化为YAML。 JSON具有三种类型的节点,分别是**Value,Object和Array**。

数据结构如下:

"name": "first": "Tatu", "last": "Saloranta" }, //Object类型节点 "title": "Jackson founder", //Value类型节点 "company": "FasterXML", //Value类型节点 "pets" : [ //Array类型节点 "type": "dog", "number": 1 "type": "fish", "number": 50

生成的YAML:

name: 
  first: Tatu
  last: Saloranta
title: Jackson founder
company: FasterXML
pets: 
- type: dog
  number: 1
- type: fish
  number: 50

JSON节点具有分层树结构。 因此,遍历整个JSON文档的最简单方法是从顶部开始,然后逐步向下遍历所有子节点。

将根节点传递给递归方法。 然后,该方法将使用提供的节点的每个子节点调用自身。

5.1测试遍历

创建一个简单的测试开始,该测试检查是否可以成功将JSON转换为YAML。

将JSON文档的根节点提供给的toYaml方法,输出转化结果:

 @Test
    public void test15() throws IOException {
        String json = "{\"name\":{\"first\":\"Tatu\",\"last\":\"Saloranta\"},\"title\":\"Jackson founder\",\"company\":\"FasterXML\",\"pets\":[{\"type\":\"dog\",\"number\":1},{\"type\":\"fish\",\"number\":50}]}";
        ObjectMapper mapper = new ObjectMapper();
        JsonNode rootNode = mapper.readTree(json);
        JsonNodeIterator jsonNodeIterator = new JsonNodeIterator();
        String s = jsonNodeIterator.toYaml(rootNode);
        System.out.println(s);
//JsonNodeIterator类
public String toYaml(JsonNode root) {
    StringBuilder yaml = new StringBuilder(); 
    processNode(root, yaml, 0); 
    return yaml.toString(); }

5.2处理不同的节点类型

需要稍微不同地处理不同类型的节点。 在processNode方法中执行此操作:

private void processNode(JsonNode jsonNode, StringBuilder yaml, int depth) {
        //是一个value
        if (jsonNode.isValueNode()) {
            yaml.append(jsonNode.asText());
        //是数组
        else if (jsonNode.isArray()) {
            for (JsonNode arrayItem : jsonNode) {
                appendNodeToYaml(arrayItem, yaml, depth, true);
        else if (jsonNode.isObject()) {
            appendNodeToYaml(jsonNode, yaml, depth, false);

首先,考虑一个Value节点。 只需调用节点的asText方法即可获取该值的String表示形式。

接下来,看一下Array节点。 Array节点中的每个项目本身都是JsonNode,因此需要遍历Array并将每个节点传递给appendNodeToYaml方法。 还需要知道这些节点是数组的一部分。

但是,节点本身不包含任何告诉的内容,因此需要将一个标志传递给appendNodeToYaml方法。

最后,要遍历每个Object节点的所有子节点。 一种选择是使用JsonNode.elements。 但是,无法从元素中确定字段名称,因为它仅包含字段值,代码如下:

 @Test
    public void test16() throws IOException {
        String json = "{\"name\":{\"first\":\"Tatu\",\"last\":\"Saloranta\"},\"title\":\"Jackson founder\",\"company\":\"FasterXML\",\"pets\":[{\"type\":\"dog\",\"number\":1},{\"type\":\"fish\",\"number\":50}]}";
        ObjectMapper mapper = new ObjectMapper();
        JsonNode rootNode = mapper.readTree(json);
        Iterator<JsonNode> elements = rootNode.elements();
        while(elements.hasNext()){
            JsonNode next = elements.next(); //紧输出值 不包含字段名称
            System.out.println(next);

输出结果如下:

Object {"first": "Tatu", "last": "Saloranta"}
Value "Jackson Founder" Value "FasterXML" 
Array  [{"type": "dog", "number": 1},{"type": "fish", "number": 50}]
不包含 Obejct Value Array

相反,可以使用JsonNode.fields,因为可以访问字段名称和值:

  @Test
    public void test17() throws IOException {
        String json = "{\"name\":{\"first\":\"Tatu\",\"last\":\"Saloranta\"},\"title\":\"Jackson founder\",\"company\":\"FasterXML\",\"pets\":[{\"type\":\"dog\",\"number\":1},{\"type\":\"fish\",\"number\":50}]}";
        ObjectMapper mapper = new ObjectMapper();
        JsonNode rootNode = mapper.readTree(json);
        Iterator<Map.Entry<String, JsonNode>> fields = rootNode.fields();
        while(fields.hasNext()){
            Map.Entry<String, JsonNode> next = fields.next();
            System.out.println(next);

输出结果如下:

name={"first":"Tatu","last":"Saloranta"}
title="Jackson founder"
company="FasterXML"
pets=[{"type":"dog","number":1},{"type":"fish","number":50}]

对于每个字段,将字段名称添加到输出中。 然后将值传递给processNode方法,将其作为子节点处理:

 private void appendNodeToYaml(JsonNode node, StringBuilder yaml, int depth, boolean isArrayItem) {
        //用于访问此JSON对象的所有字段(包含名称和值)的方法。
        Iterator<Map.Entry<String, JsonNode>> fields = node.fields();
        boolean isFirst = true;
        while (fields.hasNext()) {
            //获取 jsonNode 名称 和 值 key=value
            Map.Entry<String, JsonNode> jsonField = fields.next();
            //jsonField.getKey() 获取 key
            addFieldNameToYaml(yaml, jsonField.getKey(), depth, isArrayItem && isFirst);
            //jsonField.getValue() 获取value
            processNode(jsonField.getValue(), yaml, depth+1);
            isFirst = false;

无法从该节点知道它深度是多少。 因此,将一个称为depth的字段传递到processNode方法中,以对此进行跟踪。 每次获得子节点时,我们都会增加此值,以便可以正确缩进YAML输出中的字段:

private void addFieldNameToYaml(
  StringBuilder yaml, String fieldName, int depth, boolean isFirstInArray) {
    if (yaml.length()>0) {
        yaml.append("\n");
        int requiredDepth = (isFirstInArray) ? depth-1 : depth;
        for(int i = 0; i < requiredDepth; i++) {
            yaml.append("  ");
        if (isFirstInArray) {
            yaml.append("- ");
    yaml.append(fieldName);
    yaml.append(": ");

现在,已经准备好所有代码以遍历节点并创建YAML输出,可以运行测试以表明其有效。

完成代码如下:

public class JsonNodeIterator {
    private static final String NEW_LINE = "\n";
    private static final String FIELD_DELIMITER = ": ";
    private static final String ARRAY_PREFIX = "- ";
    private static final String YAML_PREFIX = "  ";
    public String toYaml(JsonNode root) {
        StringBuilder yaml = new StringBuilder();
        processNode(root, yaml, 0);
        return yaml.toString();
    private void processNode(JsonNode jsonNode, StringBuilder yaml, int depth) {
        //是一个value
        if (jsonNode.isValueNode()) {
            yaml.append(jsonNode.asText());
        //是数组
        else if (jsonNode.isArray()) {
            for (JsonNode arrayItem : jsonNode) {
                appendNodeToYaml(arrayItem, yaml, depth, true);
        else if (jsonNode.isObject()) {
            appendNodeToYaml(jsonNode, yaml, depth, false);
    private void appendNodeToYaml(JsonNode node, StringBuilder yaml, int depth, boolean isArrayItem) {
        //用于访问此JSON对象的所有字段(包含名称和值)的方法。
        Iterator<Map.Entry<String, JsonNode>> fields = node.fields();
        boolean isFirst = true;
        while (fields.hasNext()) {
            //获取 jsonNode 名称 和 值 key=value
            Map.Entry<String, JsonNode> jsonField = fields.next();
            //jsonField.getKey() 获取 key
            addFieldNameToYaml(yaml, jsonField.getKey(), depth, isArrayItem && isFirst);
            //jsonField.getValue() 获取value
            processNode(jsonField.getValue(), yaml, depth+1);
            isFirst = false;
    private void addFieldNameToYaml(StringBuilder yaml, String fieldName, int depth, boolean isFirstInArray) {
        if (yaml.length()>0) {
            yaml.append(NEW_LINE);
            int requiredDepth = (isFirstInArray) ? depth-1 : depth;
            for(int i = 0; i < requiredDepth; i++) {
                yaml.append(YAML_PREFIX);
            if (isFirstInArray) {
                yaml.append(ARRAY_PREFIX);
        yaml.append(fieldName);
        yaml.append(FIELD_DELIMITER);
                    1.概述使用JsonNode进行各种转换以及添加,修改和删除节点。2.创建一个节点创建节点的第一步是使用默认构造函数实例化ObjectMapper对象:ObjectMapper mapper = new ObjectMapper();由于创建ObjectMapper对象非常昂贵,因此建议将同一对象重复用于多个操作。接下来,一旦有了ObjectMapper,就有三种不同的方式来创建树节点。2.1 从头开始构建节点创建节点的最常见方法如下:JsonNode node = mapper.cre
&lt;!-- jackson begin --&gt;
&lt;dependency&gt;
    &lt;groupId&gt;com.fasterxml.jackson.core&lt;/groupId&gt;
    &lt;artifactId&gt;jackson-core&lt;/artifactId&gt;
    &lt;version&gt;2.1.4&amp
				
Json已经成为当前服务器与 WEB 应用之间数据传输的公认标准。目前java json解析工具有阿里的fastjson,google的GSON,以及SpringMVC 默认的解析工具Jackson。SpringBoot默认自带是jackson,晚上有很多json转换速率的比对,如jackson,阿里的fastjson等,不过jackson足够使用了. 使用jackson 1.pom.xml文件引用依赖包.
这段工作总会遇到使用Java处理JSON的情况,大部分都使用的是开源工具Jackson实现的。因此总结一下发上来,希望对看到的人有所帮助。 上一篇文档,我已经讲过Java如何使用Jackson来对Json进行序列化,这边我再稍微回顾一下。 Jackson有个ObjectMapper类很是实用,用于Java对象与JSON的互换。 1、Java对象转换为JSON: User user=n
&lt;!DOCTYPE html&gt; &lt;html lang="utf-8"&gt; &lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8"/&gt; &lt;head&gt; &lt;title&gt;Put data to db&lt
第一篇咱们主要学习了实体与json的相互转换的问题,但是咱们需要的是数据 你转换18遍我取不到数据也是扯淡,那么今天咱们就一起学习一下如何从使用JacksonJson字符串取值。废话不说直接上代码(注意第一篇里面的方法我都移到JsonProcessUtil里面了方便使用 )。     从Json字符串取出指定节点的值
介绍Jackson JsonNode和ObjectNode Jackson JsonNode类,完整路径为com.fasterxml.jackson.databind.JsonNode,是Jacksonjson模型(对象图模型)。Jackson能读JSONJsonNode实例,写JsonNodeJSON。本文不涉及json序列化或反序列化,主要介绍如何从头构建JsonNode对象图,之后你可以序列化为json。 1. JsonNode vs. ObjectNode The Jackson JsonN
今天在使用Jackson的时候 ,将一个json字符串转换成json对象的时候    JsonNode jsonNode = Json.parse(jsonStr);获取的是一个JsonNode对象, 然后发现这个对象并不能进行put和add操作 现提供一下解决方案 :     JsonNode jsonNode = Json.parse(jsonStr);     ObjectNode obje...
模型JSON数据内存的表示形式,这是最灵活的方法,它就类似于XML的DOM解析器。Jackson提供了模型API来生成和解析 JSON串,主要用到如下三个核心类: JsonNodeFactory:顾名思义,用来构造各种JsonNode节点的工厂。例如对象节点ObjectNode、数组节点ArrayNode等等 JsonNode:表示json节点。可以往里面塞值,从而最终构造出一颗json ObjectMapper:实现JsonNodeJSON字符串的互转 这里有个萌新的概念:JsonNo
最近在开发一个后台管理系统的权限管理模块,涉及到各种状结构的数据处理逻辑,例如:增,删,改,查等;相比普通的数组结构数据,状结构的处理就没有数组那么的直观,但是也没那么复杂,需要多一步——递归查找来对数据进行深度遍历操作,那么这里呢,博主也将开发过程总结出来的方法分享给大家,一文带你吃透JS装结构数据处理: 1、新增节点 2、删除节点 3、修改节点 4、查找节点.........
JsonNode node = ... if (node == null || !node.has("fieldName")) { // 节点为空或不包含指定名称的子节点 以上方法可以结合使用,以便更加准确地判断 Jackson JsonNode 是否为空。