如何使用Jackson递归修改JsonNode的值 [英] How to modify the value of a JsonNode recursively using Jackson
问题描述
要求:
我想对JsonNode
的内部值应用一些函数.函数可以是不同的,例如:-lowercasing
一些值或将某些值附加到值上或将值替换为某些值.如何使用Jackson
库实现该目标?请注意,JSON数据的结构可以不同,这意味着我想构建一个通用系统,该系统将接受一些路径表达式,这些路径表达式将基本上决定要更改的位置.我想使用函数式编程风格,以便可以将这些函数作为参数传递.
Requirements:
I want to apply some functions on the inner values of the JsonNode
. The functions can be different eg:- lowercasing
some values or appending something to the values or replace the values with something. How can I achieve that using Jackson
library? Note that the structure of the JSON data can be different which means I want to build a generic system which will accept some path expression which will basically decide where to change. I want to use functional programming style, so that I can pass these functions as arguments.
例如:
输入:
{
"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()
.我想在每个"value"
的所有"addresses"
内的所有"name"
属性上应用lowercase()
函数.
对于convert_to_number()
也是一样,但对于所有"dist"
属性.
In this case I have to two functions basically, lowercase()
and convert_to_number()
. I want to apply lowercase()
function on all the "name"
attribute inside all the "addresses"
of each "value"
.
same goes for convert_to_number()
, but for all the "dist"
attribute.
因此,基本上JSON
表达式将类似于以下函数:
So, basically the JSON
expressions will be something like below for the functions:
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 )
推荐答案
正如@MichalZiober在他的回答中指出的那样, JsonPath 提供了比Jackson更强大的API, 当您需要执行基于JSON路径的操作时.
As @MichalZiober in his answer already pointed out, JsonPath offers a much more powerful API than Jackson, when you need to do JSON-path-based operations.
使用方法 DocumentContext.map
您只需几行就可以解决您的问题:
Using methods JsonPath.parse
and DocumentContext.map
you can solve your problem in just a few lines:
import java.io.File;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.DocumentContext;
import com.jayway.jsonpath.JsonPath;
public class Main {
public static void main(String[] args) throws Exception {
File file = new File("input.json");
DocumentContext context = JsonPath.parse(file);
context.map("$.values[*].addresses[*].name", Main::lowerCase);
context.map("$.values[*].addresses[*].dist", Main::convertToNumber);
String json = context.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;
}
}
这篇关于如何使用Jackson递归修改JsonNode的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!