使用 Jackson 将子节点设置为根节点

发布于 2025-01-20 15:58:50 字数 2526 浏览 0 评论 0原文

问题很简单: 由此:

{
"categoryId":"some_id",    
"properties": {
            "id": "braja_de_nana",
            "displayName": "test",
            "longDescription": "<p>TESTE</p>",
            "active": true,
            "attributes": [
                {
                  "name": "made",
                  "value": "THIS_BECOMES_A_NODE_VALUE",
                  "property": "THIS_BECOMES_A_NODE_NAME"
                },
                {
                  "name": "made",
                  "value": "THIS_BECOMES_A_NODE_VALUE_2",
                  "property": "THIS_BECOMES_A_NODE_NAME_2"
                }
            ]
        }
}

更新

这应该是结果:

这意味着“属性”的每个数组元素都应该成为新的根节点

将“属性”中的“属性”设置为对象节点名称。 将“属性”中的“值”设置为对象节点值。

{
    "categoryId":"some_id",
    "THIS_BECOMES_A_NODE_VALUE":"THIS_BECOMES_A_NODE_NAME",
    "THIS_BECOMES_A_NODE_NAME_2":"THIS_BECOMES_A_NODE_VALUE_2"
    "properties": {
                "id": "braja_de_nana",
                "displayName": "test",
                "longDescription": "<p>TESTE</p>",
                "active": true
            }
    }

这对我来说是一个挑战。 我可以将新节点设置到根节点中。 已经从“属性”获得了一张映射,然后尝试使用 forEach 迭代它们,以便将结果放入一个节点中,但如图所示,我必须将“属性”设置为对象名称的键,然后获取值并设置为其值。

更新2

 @Override
    public String toOccProductDTO(ProcessProductDTO processProductDTO) throws JsonProcessingException {
        OccProductDTO occProductDTO = OccProductDTO.builder()
                .categoryId(processProductDTO.getCategoryId())
                .productType(processProductDTO.getCategoryId())
                .properties(toOccProductPropertiesDTO(processProductDTO))
                .build();
        toOccProductPropertiesDTO(processProductDTO);
        String tree = mapper.writeValueAsString(occProductDTO);

        JsonNode root = mapper.readTree(tree);
        JsonNode attributesNodeArray = ((ObjectNode) root.get("properties"))
                .remove("p_specs");

        Iterator<JsonNode> arrayNodes = attributesNodeArray.iterator();

        while (arrayNodes.hasNext()) {
            JsonNode node = arrayNodes.next();
            root = ((ObjectNode)root).set(node.get("value").asText(), node.get("property"));
        }

        System.out.println(root.toPrettyString());
        return null;
    }

我在那一行得到了一个: arrayNodes: Collection$EmptyIterator 。 我做错了什么吗?

The question is quite simple:
From this:

{
"categoryId":"some_id",    
"properties": {
            "id": "braja_de_nana",
            "displayName": "test",
            "longDescription": "<p>TESTE</p>",
            "active": true,
            "attributes": [
                {
                  "name": "made",
                  "value": "THIS_BECOMES_A_NODE_VALUE",
                  "property": "THIS_BECOMES_A_NODE_NAME"
                },
                {
                  "name": "made",
                  "value": "THIS_BECOMES_A_NODE_VALUE_2",
                  "property": "THIS_BECOMES_A_NODE_NAME_2"
                }
            ]
        }
}

UPDATE

This should be the result:

It means that every array element of 'attributes' should become a new root node.

set 'property' from 'attributes' as the object node name.
set 'value' from 'attributes' as the object node value.

{
    "categoryId":"some_id",
    "THIS_BECOMES_A_NODE_VALUE":"THIS_BECOMES_A_NODE_NAME",
    "THIS_BECOMES_A_NODE_NAME_2":"THIS_BECOMES_A_NODE_VALUE_2"
    "properties": {
                "id": "braja_de_nana",
                "displayName": "test",
                "longDescription": "<p>TESTE</p>",
                "active": true
            }
    }

This is a challenge for me.
I can set new nodes into the root node.
Already got a map from 'attributes' and then tried to iterate them with forEach in order to put the result into one single node, but instead as shown I have to take the 'property' set it to the object name´s key, then get the value and set to its value.

UPDATE 2

 @Override
    public String toOccProductDTO(ProcessProductDTO processProductDTO) throws JsonProcessingException {
        OccProductDTO occProductDTO = OccProductDTO.builder()
                .categoryId(processProductDTO.getCategoryId())
                .productType(processProductDTO.getCategoryId())
                .properties(toOccProductPropertiesDTO(processProductDTO))
                .build();
        toOccProductPropertiesDTO(processProductDTO);
        String tree = mapper.writeValueAsString(occProductDTO);

        JsonNode root = mapper.readTree(tree);
        JsonNode attributesNodeArray = ((ObjectNode) root.get("properties"))
                .remove("p_specs");

        Iterator<JsonNode> arrayNodes = attributesNodeArray.iterator();

        while (arrayNodes.hasNext()) {
            JsonNode node = arrayNodes.next();
            root = ((ObjectNode)root).set(node.get("value").asText(), node.get("property"));
        }

        System.out.println(root.toPrettyString());
        return null;
    }

I got an: arrayNodes: Collection$EmptyIterator at that line.
Am I doing something wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

最冷一天 2025-01-27 15:58:50

如果您尝试将属性属于根节点,则可以删除该节点并将其字段添加到根部。

“属性”节点是一个具有长度1的数组,因此您必须获取数组的第一个元素才能获取属性字段。

ObjectMapper mapper = new ObjectMapper();

JsonNode root = mapper.readTree(json);

JsonNode attributesNodeArray = ((ObjectNode) root.get("properties"))
        .remove("attributes");

JsonNode attributesNode = attributesNodeArray.get(0);

Iterator<String> fieldNames = attributesNode.fieldNames();

while (fieldNames.hasNext()) {
    String name = fieldNames.next();
    root = ((ObjectNode)root).set(name, attributesNode.get(name));
}

System.out.println(root.toPrettyString());

输出:

{
  "categoryId" : "some_id",
  "properties" : {
    "id" : "braja_de_nana",
    "displayName" : "test",
    "longDescription" : "<p>TESTE</p>",
    "active" : true
  },
  "name" : "made",
  "value" : "some value",
  "property" : "some_value"
}

更新

对于更新的问题,您可以执行以下操作:

ObjectMapper mapper = new ObjectMapper();

JsonNode root = mapper.readTree(json);

JsonNode attributesNodeArray = ((ObjectNode) root.get("properties"))
        .remove("attributes");

Iterator<JsonNode> arrayNodes = attributesNodeArray.iterator();

while (arrayNodes.hasNext()) {
    JsonNode node = arrayNodes.next();
    root = ((ObjectNode)root).set(node.get("value").asText(), node.get("property"));
}

System.out.println(root.toPrettyString());

输出:

{
  "categoryId" : "some_id",
  "properties" : {
    "id" : "braja_de_nana",
    "displayName" : "test",
    "longDescription" : "<p>TESTE</p>",
    "active" : true
  },
  "THIS_BECOMES_A_NODE_VALUE" : "THIS_BECOMES_A_NODE_NAME",
  "THIS_BECOMES_A_NODE_VALUE_2" : "THIS_BECOMES_A_NODE_NAME_2"
}

If you are trying to the attributes to the root node, you can remove that node and add its fields to the root.

The "attributes" node is an array with length 1, so you have to get the first element of the array to get the attribute fields.

ObjectMapper mapper = new ObjectMapper();

JsonNode root = mapper.readTree(json);

JsonNode attributesNodeArray = ((ObjectNode) root.get("properties"))
        .remove("attributes");

JsonNode attributesNode = attributesNodeArray.get(0);

Iterator<String> fieldNames = attributesNode.fieldNames();

while (fieldNames.hasNext()) {
    String name = fieldNames.next();
    root = ((ObjectNode)root).set(name, attributesNode.get(name));
}

System.out.println(root.toPrettyString());

Output:

{
  "categoryId" : "some_id",
  "properties" : {
    "id" : "braja_de_nana",
    "displayName" : "test",
    "longDescription" : "<p>TESTE</p>",
    "active" : true
  },
  "name" : "made",
  "value" : "some value",
  "property" : "some_value"
}

UPDATE

For the updated question, you can do the following:

ObjectMapper mapper = new ObjectMapper();

JsonNode root = mapper.readTree(json);

JsonNode attributesNodeArray = ((ObjectNode) root.get("properties"))
        .remove("attributes");

Iterator<JsonNode> arrayNodes = attributesNodeArray.iterator();

while (arrayNodes.hasNext()) {
    JsonNode node = arrayNodes.next();
    root = ((ObjectNode)root).set(node.get("value").asText(), node.get("property"));
}

System.out.println(root.toPrettyString());

Output:

{
  "categoryId" : "some_id",
  "properties" : {
    "id" : "braja_de_nana",
    "displayName" : "test",
    "longDescription" : "<p>TESTE</p>",
    "active" : true
  },
  "THIS_BECOMES_A_NODE_VALUE" : "THIS_BECOMES_A_NODE_NAME",
  "THIS_BECOMES_A_NODE_VALUE_2" : "THIS_BECOMES_A_NODE_NAME_2"
}
不羁少年 2025-01-27 15:58:50

也许它比预期的要复杂。
事实证明,我用双簧管的帮助解决了问题。尽管他通过实施和一些变化错过了一些要点,但我可以实现目标。

         //Converts the parsed objects into Json String
                String tree = mapper.writeValueAsString(occProductDTO);
        
                //Reads the json string to JsonNode in order to manipulate it
                JsonNode root = mapper.readTree(tree);

//Sets the chosen node where the new nodes should be created
 JsonNode properties = root.path("properties");
        
//maps the two attribs needed
                Map<String, String> attribs = processProductDTO.getProductDTO().getAttributes().stream()
                        .collect(Collectors.toMap(AttributeDTO::getProperty, AttributeDTO::getValue));
    
    //Converts each attrib into a String list
                List<String> props = attribs.entrySet().stream()
                        .sorted(Comparator.comparing(Map.Entry<String, String>::getValue).reversed())
                        .map(Map.Entry::getKey)
                        .collect(Collectors.toList());
                List<String> names = attribs.entrySet()
                        .stream()                .sorted(Comparator.comparing(Map.Entry<String,String>::getValue).reversed())
                        .map(Map.Entry::getValue)
                        .collect(Collectors.toList());
        
    //iterates over the two lists adding the attribs to their corresponding position
                Iterator<String> arrayNodes = props.listIterator();
                Iterator<String> arrayNodes2 = names.listIterator();
        
                while (arrayNodes.hasNext()) {
                    String node = arrayNodes.next();
                    String node2 = arrayNodes2.next();
                    properties = ((ObjectNode)properties).put(node, node2);
                }
        
                return mapper.writeValueAsString(root);
            }

最后,我不是通过@post传递Java对象,而是通过使用“消费= application/json,caredues =“ application.json”)传递JSON字符串

也许可以实现并更好地实现使用Java 8流,但现在起作用。
欢迎改进代码的建议!

Maybe it was more complex than expected.
It turns out that I solved the problem with Oboe´s help. Although he missed some points through his implementation plus some changes I could achieve the goal.

         //Converts the parsed objects into Json String
                String tree = mapper.writeValueAsString(occProductDTO);
        
                //Reads the json string to JsonNode in order to manipulate it
                JsonNode root = mapper.readTree(tree);

//Sets the chosen node where the new nodes should be created
 JsonNode properties = root.path("properties");
        
//maps the two attribs needed
                Map<String, String> attribs = processProductDTO.getProductDTO().getAttributes().stream()
                        .collect(Collectors.toMap(AttributeDTO::getProperty, AttributeDTO::getValue));
    
    //Converts each attrib into a String list
                List<String> props = attribs.entrySet().stream()
                        .sorted(Comparator.comparing(Map.Entry<String, String>::getValue).reversed())
                        .map(Map.Entry::getKey)
                        .collect(Collectors.toList());
                List<String> names = attribs.entrySet()
                        .stream()                .sorted(Comparator.comparing(Map.Entry<String,String>::getValue).reversed())
                        .map(Map.Entry::getValue)
                        .collect(Collectors.toList());
        
    //iterates over the two lists adding the attribs to their corresponding position
                Iterator<String> arrayNodes = props.listIterator();
                Iterator<String> arrayNodes2 = names.listIterator();
        
                while (arrayNodes.hasNext()) {
                    String node = arrayNodes.next();
                    String node2 = arrayNodes2.next();
                    properties = ((ObjectNode)properties).put(node, node2);
                }
        
                return mapper.writeValueAsString(root);
            }

In the end, instead of passing a java object via @Post, I´m passing a json String by using "consumes = application/json, produces = "application.json"

That´s it!

Maybe it could be achieved and better implemented with java 8 stream, but for now it works.
Suggestion to improve the code are welcome!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文