java - 如何使用 JsonPath 向 Json 添加新节点?
问题描述
我正在使用 JSON 并面临一些问题。
我想在 JSON 对象中插入/更新路径。在路径不存在的情况下,它将被创建然后我插入一个新值。如果它退出,它将被一个新值更新
例如,我想添加这样的新路径:
val doc = JsonPath.parse(jsonString)
doc.add("$.user.name", "John")
但我总是收到此错误,因为路径不存在:
com.jayway.jsonpath.PathNotFoundException 类:路径 $['user'] 中缺少属性
因此,如果它不存在,我想创建一个新路径。
这是我的代码,但jsonString
不会改变:
var jsonString = "{}" val conf = Configuration.defaultConfiguration().addOptions(Option.DEFAULT_PATH_LEAF_TO_NULL).addOptions(Option.SUPPRESS_EXCEPTIONS)
JsonPath.using(conf).parse(jsonString).set(JsonPath.compile("$.user.name"), "John")
Log.d("TAG", "new json = $jsonString")
请给我你的建议。非常感谢!!
解决方案
我尝试了三个支持 JsonPath/JsonPointer(Jackson、JsonPath 和 JSON-P)的不同 JSON 库,但在缺少父节点的情况下,它们都无法重建 JSON 对象层次结构。所以我想出了自己的解决方案,使用 Jackson/JsonPointer 向 JSON 对象添加新值,因为它允许浏览 JsonPointer 部分。
private static final ObjectMapper mapper = new ObjectMapper();
public void setJsonPointerValue(ObjectNode node, JsonPointer pointer, JsonNode value) {
JsonPointer parentPointer = pointer.head();
JsonNode parentNode = node.at(parentPointer);
String fieldName = pointer.last().toString().substring(1);
if (parentNode.isMissingNode() || parentNode.isNull()) {
parentNode = StringUtils.isNumeric(fieldName) ? mapper.createArrayNode() : mapper.createObjectNode();
setJsonPointerValue(parentPointer, parentNode); // recursively reconstruct hierarchy
}
if (parentNode.isArray()) {
ArrayNode arrayNode = (ArrayNode) parentNode;
int index = Integer.valueOf(fieldName);
// expand array in case index is greater than array size (like JavaScript does)
for (int i = arrayNode.size(); i <= index; i++) {
arrayNode.addNull();
}
arrayNode.set(index, value);
} else if (parentNode.isObject()) {
((ObjectNode) parentNode).set(fieldName, value);
} else {
throw new IllegalArgumentException("`" + fieldName + "` can't be set for parent node `"
+ parentPointer + "` because parent is not a container but " + parentNode.getNodeType().name());
}
}
用法:
ObjectNode rootNode = mapper.createObjectNode();
setJsonPointerValue(rootNode, JsonPointer.compile("/root/array/0/name"), new TextNode("John"));
setJsonPointerValue(rootNode, JsonPointer.compile("/root/array/0/age"), new IntNode(17));
setJsonPointerValue(rootNode, JsonPointer.compile("/root/array/4"), new IntNode(12));
setJsonPointerValue(rootNode, JsonPointer.compile("/root/object/num"), new IntNode(81));
setJsonPointerValue(rootNode, JsonPointer.compile("/root/object/str"), new TextNode("text"));
setJsonPointerValue(rootNode, JsonPointer.compile("/descr"), new TextNode("description"));
System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(rootNode));
这将生成并打印以下 JSON 对象:
{
"root" : {
"array" : [ {
"name" : "John",
"age" : 17
}, null, null, null, 12 ],
"object" : {
"num" : 81,
"str" : "text"
}
},
"descr" : "description"
}
当然,这并不涵盖所有极端情况,但适用于大多数情况。希望这对其他人有帮助。
推荐阅读
- flutter - Dart 在一行上声明多个变量
- asp.net - Asp.Net Razor 自定义样式单选列表框
- java - 如何在多个类中抽象出具有不同返回类型的相同方法
- python - Python单例设计模式 - 静态方法与类方法方法
- react-native - 我是否必须制作单独的 MyComponent.android.js 文件才能使用 SafeArea
- android - Android studio 3.4.2 R8 混淆器不混淆类名,只混淆里面的java代码
- tex - 为什么我的 sage 命令的结果变成了问号?
- javascript - Office.js 如何将字符样式应用于选定的单词
- c# - 注销用户 OneDrive API
- reactjs - 如何删除 Chartjs 中的鬼线?