首页 > 解决方案 > 如何使用 Jackson 递归地修改 JsonNode 的值

问题描述

要求:
我想对JsonNode. 功能可以不同,例如:-lowercasing一些值或将某些内容附加到这些值或用某些内容替换这些值。我怎样才能使用Jackson库来实现呢?请注意,JSON 数据的结构可能不同,这意味着我想构建一个通用系统,该系统将接受一些路径表达式,该路径表达式基本上将决定更改的位置。我想使用函数式编程风格,以便可以将这些函数作为参数传递。

例如:

输入:

{
  "name": "xyz",
  "values": [
    {
      "id": "xyz1",
      "sal": "1234",
      "addresses": [
        {
          "id": "add1",
          "name": "ABCD",
          "dist": "123"
        },
        {
          "id": "add2",
          "name": "abcd3",
          "dist": "345"
        }
      ]
    },
    {
      "id": "xyz2",
      "sal": "3456",
      "addresses": [
        {
          "id": "add1",
          "name": "abcd",
          "dist": "123"
        },
        {
          "id": "add2",
          "name": "XXXXX",
          "dist": "345"
        }
      ]
    }
  ]
}

在这种情况下,我基本上必须有两个功能,lowercase()并且convert_to_number(). 我想对each中的所有属性应用lowercase()函数。同样适用于,但适用于所有属性。"name""addresses""value"convert_to_number()"dist"

因此,基本上,JSON函数的表达式如下所示:

lowercase() : /values/*/addresses/*/name
convert_to_number() : /values/*/addresses/*/dist

输出:

{
  "name": "xyz",
  "values": [
    {
      "id": "xyz1",
      "sal": "1234",
      "addresses": [
        {
          "id": "add1",
          "name": "abcd",
          "dist": 123
        },
        {
          "id": "add2",
          "name": "abcd3",
          "dist": 345
        }
      ]
    },
    {
      "id": "xyz2",
      "sal": "3456",
      "addresses": [
        {
          "id": "add1",
          "name": "abcd",
          "dist": 123
        },
        {
          "id": "add2",
          "name": "xxxx",
          "dist": 345
        }
      ]
    }
  ]
}

客户端代码:

JsonNode jsonNode = ...
applyFunctionsRecursivelyBasedOnExpr(JsonNode jsonNode, String expr, Function )

标签: javajsonjacksonjsonpathjackson-databind

解决方案


正如@MichalZiober 在他的回答中已经指出的那样,当您需要执行基于 JSON 路径的操作时, JsonPath提供了比杰克逊更强大的 API。

使用方法JsonPath.parseWriteContext.map 您只需几行就可以解决您的问题:

import java.io.File;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.JsonPath;

public class Main {

    public static void main(String[] args) throws Exception {
        File file = new File("input.json");
        String json = JsonPath.parse(file)
                .map("$.values[*].addresses[*].name", Main::lowerCase)
                .map("$.values[*].addresses[*].dist", Main::convertToNumber)
                .jsonString();
        System.out.println(json);
    }

    private static Object lowerCase(Object currentValue, Configuration configuration) {
        if (currentValue instanceof String)
            return ((String)currentValue).toLowerCase();
        return currentValue;
    }

    private static Object convertToNumber(Object currentValue, Configuration configuration) {
        if (currentValue instanceof String)
            return Integer.valueOf((String)currentValue);
        return currentValue;
    }
}

推荐阅读