如何更新这个 jackson JsonNode 中的某个值?
How to update a certain value inside this jackson JsonNode?
TLDR:
我想将 JsonNode 键 dependsOn
和 return 的某些值更新为 JsonNode 结果。目前我正在将该值转换为 String
,对字符进行切片,然后使用 ObjectMapper
将字符串转换回 JsonNode
我有一个 json 对象,如下所示
{
"name": "somename",
"type": "sometype",
"description": "some desc",
"properties": {
"path": "some path",
"dependsOn": [
"ABC:zzz","DEF:sdc","GHI:ere"
],
"checkpoint": "some checkpoint",
"format": "some format",
"output": "some output",
"table": "some table"
}
}
我目前正在解析上面的 json 数据并获取 dependsOn
作为 JsonNode 元素(如下所示)
JsonNode components = model.get("properties");
JsonNode dependsOn = components.get("dependsOn");
当我打印 dependsOn
时,它看起来像这样 "["ABC:zzz","DEF:sdc","GHI:ere"]"
我的要求是 strip
dependsOn
数组 :
之后的所有内容
下面的代码帮助我将 JsonNode 转换为 String,然后剥离 :whatever
然后将其转换回 JsonNode
if (dependsOn != null && !dependsOn.isEmpty()) {
String dependsOnString =
components
.get("dependsOn")
.get(0)
.textValue()
.substring(
0,
(components.get("dependsOn").get(0).textValue().lastIndexOf(":") != -1)
? components.get("dependsOn").get(0).textValue().lastIndexOf(":")
: components.get("dependsOn").get(0).textValue().length());
ObjectMapper mapper = new ObjectMapper();
dependsOn = mapper.readTree("[\"" + dependsOnString + "\"]");
}
输入:
"["ABC:zzz","DEF:sdc","GHI:ere"]"
输出
"["ABC","DEF:sdc","GHI:ere"]"
上面的代码只去掉了数组的第一个元素,我可以循环并对其余元素执行相同的操作。但是我有几个关于我正在尝试做的事情的问题
Firstly, am I doing this in a right way or is there a simpler
technique to do this? instead of converting it to string and then
again to JsonNode..
Next, I've only done this to the first element of the array
and I want to loop through and do this for all the elements of the array
. Is there a simpler solution to this instead of using a for/while loop?
您可以在将 dependsOn
转换为 ArrayNode
并为其设置值后对其进行迭代:
ArrayNode array = ((ArrayNode) dependsOn);
List<String> newValues = new ArrayList<>();
for(int i=0;i<array.size();i++) {
newValues.add(array.get(i).asText().split(":")[0]);
}
array.removeAll();
newValues.forEach(array::add);
编辑: 如果您不想更新原始 dependsOn
,请使用:
JsonNode copy = dependsOn.deepCopy();
// or you could invoke `deepCopy` on the `ArrayNode` as well
现在传递这个copy
对象进行切片操作。使原来的json保持不变
这应该可以工作,无需转换为字符串并再次解析为 jsonNode
JsonNode prop = node.get("properties");
JsonNode arrayCopy = prop.get("dependsOn").deepCopy();
var array = ((ObjectNode)prop).putArray("dependsOn");
IntStream.range(0, arrayCopy.size())
.forEach(index -> {
String elem = arrayCopy.get(index).asText();
String finalElem = elem.substring(0,elem.contains(":") ? elem.lastIndexOf(':') : elem.length());
array.add(finalElem);
});
因为我的用例表明我的 dependsOn
值不应该在节点级别被覆盖,所以我不得不将 JsonNode 转换为 String 然后使用正则表达式匹配器将每个元素中的 :xyz
替换为空字符串,然后 将其 转换回 JsonNode
String pattern = ":[a-zA-Z]+";
String newDependsOn = dependsOn.toString().replaceAll(pattern, "");
ObjectMapper mapper = new ObjectMapper();
dependsOn = mapper.readTree(newDependsOn);
@Gautham 的解决方案也确实有效,但我认为它在根部被压倒了,旧值在循环外不再可用
TLDR:
我想将 JsonNode 键 dependsOn
和 return 的某些值更新为 JsonNode 结果。目前我正在将该值转换为 String
,对字符进行切片,然后使用 ObjectMapper
将字符串转换回 JsonNode
我有一个 json 对象,如下所示
{
"name": "somename",
"type": "sometype",
"description": "some desc",
"properties": {
"path": "some path",
"dependsOn": [
"ABC:zzz","DEF:sdc","GHI:ere"
],
"checkpoint": "some checkpoint",
"format": "some format",
"output": "some output",
"table": "some table"
}
}
我目前正在解析上面的 json 数据并获取 dependsOn
作为 JsonNode 元素(如下所示)
JsonNode components = model.get("properties");
JsonNode dependsOn = components.get("dependsOn");
当我打印 dependsOn
时,它看起来像这样 "["ABC:zzz","DEF:sdc","GHI:ere"]"
我的要求是 strip
dependsOn
数组 :
之后的所有内容
下面的代码帮助我将 JsonNode 转换为 String,然后剥离 :whatever
然后将其转换回 JsonNode
if (dependsOn != null && !dependsOn.isEmpty()) {
String dependsOnString =
components
.get("dependsOn")
.get(0)
.textValue()
.substring(
0,
(components.get("dependsOn").get(0).textValue().lastIndexOf(":") != -1)
? components.get("dependsOn").get(0).textValue().lastIndexOf(":")
: components.get("dependsOn").get(0).textValue().length());
ObjectMapper mapper = new ObjectMapper();
dependsOn = mapper.readTree("[\"" + dependsOnString + "\"]");
}
输入:
"["ABC:zzz","DEF:sdc","GHI:ere"]"
输出
"["ABC","DEF:sdc","GHI:ere"]"
上面的代码只去掉了数组的第一个元素,我可以循环并对其余元素执行相同的操作。但是我有几个关于我正在尝试做的事情的问题
Firstly, am I doing this in a right way or is there a simpler technique to do this? instead of converting it to string and then again to JsonNode..
Next, I've only done this to the
first element of the array
and I want to loop through and do this forall the elements of the array
. Is there a simpler solution to this instead of using a for/while loop?
您可以在将 dependsOn
转换为 ArrayNode
并为其设置值后对其进行迭代:
ArrayNode array = ((ArrayNode) dependsOn);
List<String> newValues = new ArrayList<>();
for(int i=0;i<array.size();i++) {
newValues.add(array.get(i).asText().split(":")[0]);
}
array.removeAll();
newValues.forEach(array::add);
编辑: 如果您不想更新原始 dependsOn
,请使用:
JsonNode copy = dependsOn.deepCopy();
// or you could invoke `deepCopy` on the `ArrayNode` as well
现在传递这个copy
对象进行切片操作。使原来的json保持不变
这应该可以工作,无需转换为字符串并再次解析为 jsonNode
JsonNode prop = node.get("properties");
JsonNode arrayCopy = prop.get("dependsOn").deepCopy();
var array = ((ObjectNode)prop).putArray("dependsOn");
IntStream.range(0, arrayCopy.size())
.forEach(index -> {
String elem = arrayCopy.get(index).asText();
String finalElem = elem.substring(0,elem.contains(":") ? elem.lastIndexOf(':') : elem.length());
array.add(finalElem);
});
因为我的用例表明我的 dependsOn
值不应该在节点级别被覆盖,所以我不得不将 JsonNode 转换为 String 然后使用正则表达式匹配器将每个元素中的 :xyz
替换为空字符串,然后 将其 转换回 JsonNode
String pattern = ":[a-zA-Z]+";
String newDependsOn = dependsOn.toString().replaceAll(pattern, "");
ObjectMapper mapper = new ObjectMapper();
dependsOn = mapper.readTree(newDependsOn);
@Gautham 的解决方案也确实有效,但我认为它在根部被压倒了,旧值在循环外不再可用