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

Set child node as root node using jackson

问题很简单: 来自:

{
"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"
                }
            ]
        }
}

更新

这应该是结果:

表示'attributes'的每个数组元素都应该成为新的根节点

将'property' from 'attributes' 设置为对象节点名称。 将 'value' from 'attributes' 设置为对象节点值。

{
    "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
            }
    }

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

更新 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。 我做错了什么吗?

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

"attributes"节点是一个长度为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"
}

也许它比预期的要复杂。 事实证明,我在双簧管的帮助下解决了这个问题。虽然他通过他的实现和一些改变我可以达到目标。

         //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 对象,而是通过使用 "consumes = application/json 传递 json 字符串,产生=“application.json”

就是这样!

也许它可以通过 java 8 流实现并更好地实现,但目前它可以工作。 欢迎提出改进代码的建议!