如何更新这个 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 的解决方案也确实有效,但我认为它在根部被压倒了,旧值在循环外不再可用