使用 Java 修改指定节点中的 json 字段值
Modify json field value in specified node using Java
例如我有Json这样的
{
name: Alex,
lastName: Smith,
delivery: {
street: 7599 King George Blvd,
name : PIETER CIERE
},
paymentAddressData: [
{
email: mail@email.com,
name: Bobby,
phone2: 123456
},
{
email: mail@email.com,
name: Bobby,
phone2: 123456
}
]
}
而且我需要更改“名称”字段中的值,仅在所有条目的根节点和“paymentAddressData”arrayNode 中。在所有其他地方,价值必须保持原样。
我如何使用 Jackson 或其他工具来实现它?如有任何建议,我们将不胜感激!
我为我们的测试自动化(通过 REST Assured)实现了我自己的动态方法,您可以在其中使用 KeyPath 约定(见下文)填充 HashMap,以便 一次修改任意多个键 和最后 return JSONObject 和 JSONArray 的相应新 Json-String(仅以一个“[”和“]”开始和结束)。我从来不需要使用修改 JSON 以多个方括号开头的数组,这些方括号不应该经常使用。
只需将您的来源 JSON 提取为修改它的字符串,然后根据 file/path.
回写
这是一个 JSON 示例:
{
"personalDetails": [
{
"name": "John",
"city": "Berlin",
"job": "Teacher",
"age": 42,
"children": [
{
"name": "Kevin",
"city": "Berlin",
"age": 14
},
{
"name": "Lisa",
"city": "Berlin",
"age": 8
}
]
},
{
"name": "Mark",
"city": "Oslo",
"job": "Doctor",
"children": []
}
]
}
例如,您要修改以下键:
年龄(丽莎) -> 来自:8
,到:9
,KeyPath:"personalDetails[0].children[1].age"
工作(标记) -> 来自:"Doctor"
,到:"Chiropractor"
,KeyPath:"personalDetails[1].job"
根据我的示例,使用您给定的 Json-String 并遵循 HashMap 来填充下面我的动态方法中的参数:
HashMap<String, Object> modifyMap = new HashMap<String, Object>() {{
put("personalDetails[0].children[1].age", 9);
put("personalDetails[1].job", "Chiropractor");
}};
使用提取的、修改的 Json-String
调用此方法
// Modify any given JsonObject or JsonArray due to KeyPath conventions
protected static String modifiedJson(String oldJson, Map<String, Object> modifyMap) {
JSONObject defaultJson = new JSONObject("{}");
Object newJson = defaultJson;
Pattern pattern = Pattern.compile("\[(\d+)]");
for (String keyPath : modifyMap.keySet()) {
String[] keyPathTrimmings = keyPath.split("\.");
int sizeOfTrimmings = keyPathTrimmings.length;
JSONObject[] jsonObjects = new JSONObject[sizeOfTrimmings];
Matcher matcher = pattern.matcher(keyPathTrimmings[sizeOfTrimmings - 1]);
newJson = matcher.find(0) ?
newJson.equals(defaultJson) ? new JSONArray(oldJson) : newJson :
newJson.equals(defaultJson) ? new JSONObject(oldJson) : newJson;
jsonObjects[0] = matcher.find(0) ?
newJson instanceof JSONArray ? ((JSONArray) newJson).getJSONObject(Integer.parseInt(matcher.group(1))) : defaultJson :
newJson instanceof JSONObject ? (JSONObject) newJson : defaultJson;
for (int pos = 0; pos < sizeOfTrimmings; pos++) {
String actualKey = keyPathTrimmings[pos].replaceAll("\[(\d+)]", "");
if (pos == sizeOfTrimmings - 1) {
jsonObjects[pos].put(actualKey, modifyMap.get(keyPath));
} else {
matcher = pattern.matcher(keyPathTrimmings[pos]);
jsonObjects[pos + 1] = matcher.find(0) ?
jsonObjects[pos].getJSONArray(actualKey).getJSONObject(Integer.parseInt(matcher.group(1))) :
jsonObjects[pos].getJSONObject(actualKey);
}
}
}
return newJson.toString();
}
与其使用 Jackson,我更喜欢 JsonPath 库,
因为它提供了更强大的 API 来访问和修改
JSON 内容以 path-based 方式。
对于一些示例,我建议阅读文章 Baeldung - Introduction to JsonPath.
使用方法JsonPath.parse
and WriteContext.set
你可以用几行来完成。
以下代码将根节点中的名称替换为 "Alice"
"Charlie"
.
所有 paymentAddressData
个节点中的名称
File file = new File("example.json");
String json = JsonPath.parse(file)
.set("$.name", "Alice")
.set("$.paymentAddressData[*].name", "Charlie")
.jsonString();
System.out.println(json);
如果您想要另一个值来替换 JSON 名称,
那么您将需要调整上面代码中的 .set(...)
调用
根据您的需要。
对于更复杂的逻辑,您可能需要使用 .map(...)
而不是 .set(...)
.
例如我有Json这样的
{
name: Alex,
lastName: Smith,
delivery: {
street: 7599 King George Blvd,
name : PIETER CIERE
},
paymentAddressData: [
{
email: mail@email.com,
name: Bobby,
phone2: 123456
},
{
email: mail@email.com,
name: Bobby,
phone2: 123456
}
]
}
而且我需要更改“名称”字段中的值,仅在所有条目的根节点和“paymentAddressData”arrayNode 中。在所有其他地方,价值必须保持原样。 我如何使用 Jackson 或其他工具来实现它?如有任何建议,我们将不胜感激!
我为我们的测试自动化(通过 REST Assured)实现了我自己的动态方法,您可以在其中使用 KeyPath 约定(见下文)填充 HashMap,以便 一次修改任意多个键 和最后 return JSONObject 和 JSONArray 的相应新 Json-String(仅以一个“[”和“]”开始和结束)。我从来不需要使用修改 JSON 以多个方括号开头的数组,这些方括号不应该经常使用。
只需将您的来源 JSON 提取为修改它的字符串,然后根据 file/path.
回写这是一个 JSON 示例:
{
"personalDetails": [
{
"name": "John",
"city": "Berlin",
"job": "Teacher",
"age": 42,
"children": [
{
"name": "Kevin",
"city": "Berlin",
"age": 14
},
{
"name": "Lisa",
"city": "Berlin",
"age": 8
}
]
},
{
"name": "Mark",
"city": "Oslo",
"job": "Doctor",
"children": []
}
]
}
例如,您要修改以下键:
年龄(丽莎) -> 来自:
8
,到:9
,KeyPath:"personalDetails[0].children[1].age"
工作(标记) -> 来自:
"Doctor"
,到:"Chiropractor"
,KeyPath:"personalDetails[1].job"
根据我的示例,使用您给定的 Json-String 并遵循 HashMap 来填充下面我的动态方法中的参数:
HashMap<String, Object> modifyMap = new HashMap<String, Object>() {{
put("personalDetails[0].children[1].age", 9);
put("personalDetails[1].job", "Chiropractor");
}};
使用提取的、修改的 Json-String
调用此方法// Modify any given JsonObject or JsonArray due to KeyPath conventions
protected static String modifiedJson(String oldJson, Map<String, Object> modifyMap) {
JSONObject defaultJson = new JSONObject("{}");
Object newJson = defaultJson;
Pattern pattern = Pattern.compile("\[(\d+)]");
for (String keyPath : modifyMap.keySet()) {
String[] keyPathTrimmings = keyPath.split("\.");
int sizeOfTrimmings = keyPathTrimmings.length;
JSONObject[] jsonObjects = new JSONObject[sizeOfTrimmings];
Matcher matcher = pattern.matcher(keyPathTrimmings[sizeOfTrimmings - 1]);
newJson = matcher.find(0) ?
newJson.equals(defaultJson) ? new JSONArray(oldJson) : newJson :
newJson.equals(defaultJson) ? new JSONObject(oldJson) : newJson;
jsonObjects[0] = matcher.find(0) ?
newJson instanceof JSONArray ? ((JSONArray) newJson).getJSONObject(Integer.parseInt(matcher.group(1))) : defaultJson :
newJson instanceof JSONObject ? (JSONObject) newJson : defaultJson;
for (int pos = 0; pos < sizeOfTrimmings; pos++) {
String actualKey = keyPathTrimmings[pos].replaceAll("\[(\d+)]", "");
if (pos == sizeOfTrimmings - 1) {
jsonObjects[pos].put(actualKey, modifyMap.get(keyPath));
} else {
matcher = pattern.matcher(keyPathTrimmings[pos]);
jsonObjects[pos + 1] = matcher.find(0) ?
jsonObjects[pos].getJSONArray(actualKey).getJSONObject(Integer.parseInt(matcher.group(1))) :
jsonObjects[pos].getJSONObject(actualKey);
}
}
}
return newJson.toString();
}
与其使用 Jackson,我更喜欢 JsonPath 库, 因为它提供了更强大的 API 来访问和修改 JSON 内容以 path-based 方式。 对于一些示例,我建议阅读文章 Baeldung - Introduction to JsonPath.
使用方法JsonPath.parse
and WriteContext.set
你可以用几行来完成。
以下代码将根节点中的名称替换为 "Alice"
"Charlie"
.
paymentAddressData
个节点中的名称
File file = new File("example.json");
String json = JsonPath.parse(file)
.set("$.name", "Alice")
.set("$.paymentAddressData[*].name", "Charlie")
.jsonString();
System.out.println(json);
如果您想要另一个值来替换 JSON 名称,
那么您将需要调整上面代码中的 .set(...)
调用
根据您的需要。
对于更复杂的逻辑,您可能需要使用 .map(...)
而不是 .set(...)
.