使用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 流实现并更好地实现,但目前它可以工作。
欢迎提出改进代码的建议!
问题很简单: 来自:
{
"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 流实现并更好地实现,但目前它可以工作。 欢迎提出改进代码的建议!