java 使用带有路径的 Gson
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26087701/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using Gson with a path
提问by Eduardo
Using a simple Json file e.g:
使用一个简单的 Json 文件,例如:
{"menu": {
"id": "file",
"value": "File",
"popup": {
"menuitem": [
{"value": "New", "onclick": "CreateNewDoc()"},
{"value": "Open", "onclick": "OpenDoc()"},
{"value": "Close", "onclick": "CloseDoc()"}
]
}
}}
I want to be able to get the JsonArray
named menuitem
using a path:
我希望能够使用路径获取JsonArray
命名menuitem
:
String path = "menu.popup.menuitem"
I tried to do this using:
我尝试使用以下方法执行此操作:
public static JsonElement fromString(String json, String path) throws JsonSyntaxException {
JsonObject obj = GsonBuilder.create().fromJson(json, JsonObject.class);
String[] seg = path.split(".");
for (String element : seg) {
if (obj != null) {
obj = obj.get(element).getAsJsonObject();
} else {
return null;
}
}
return obj
}
with:
和:
JsonElement jsonElement = fromString(json, path);
But when I try isJsonArray()
the return value is false
. When doing the extra sanity check using Gson.toJson(jsonElement)
the output is the full json String (above) that was inputted originally.
What's going wrong?
但是当我尝试isJsonArray()
返回值是false
. 使用Gson.toJson(jsonElement)
输出进行额外的完整性检查时,输出是最初输入的完整 json 字符串(上图)。怎么了?
采纳答案by Pshemo
split
uses regex to find places on which string should be split, but .
in regex is special character which represents "any character beside line separators", which means that you are actually splitting on each character. So for string like
split
使用正则表达式查找应拆分字符串的位置,但.
在正则表达式中是特殊字符,表示“行分隔符旁边的任何字符”,这意味着您实际上是在每个字符上拆分。所以对于像这样的字符串
"foo"
"foo".split(".")
will split on f
, o
, o
"foo".split(".")
将分裂于f
, o
,o
"foo"
^^^
which means you will get as result array with four empty strings (3 splits give 4 elements).
这意味着您将获得带有四个空字符串的结果数组(3 个拆分给出 4 个元素)。
["", "", "", ""]
Actually I lied here because split(regex)
does one additional thing: it removes trailing empty strings from result array, but your array contains only empty strings, which means that they will all be removed, so split(".")
will return just empty array []
so your loop will not iterate even once (that is why your method returns unmodified obj
).
实际上我在这里撒谎是因为split(regex)
做了一件额外的事情:它从结果数组中删除了尾随的空字符串,但是你的数组只包含空字符串,这意味着它们都将被删除,所以split(".")
只会返回空数组,[]
这样你的循环就不会迭代一次(这就是您的方法返回未修改的原因obj
)。
To get rid of this problem you will need to make .
literal (you need to escape it). To do so you can use for instance split("\\.")
or split("[.]")
or split(Pattern.quote(".")
which work same as split("\\Q.\\E")
- it adds quotation area.
为了摆脱这个问题,你需要做.
文字(你需要逃避它)。为此,您可以使用例如split("\\.")
orsplit("[.]")
或split(Pattern.quote(".")
which 与工作相同split("\\Q.\\E")
- 它添加了引用区域。
Also inside loop you should first check type of Json you are handling, because getAsJsonObject
will fail if Json is array. So your code should probably look like
同样在循环内部,您应该首先检查您正在处理的 Json 类型,因为getAsJsonObject
如果 Json 是数组,则会失败。所以你的代码应该看起来像
public static JsonElement fromString(String json, String path)
throws JsonSyntaxException {
JsonObject obj = new GsonBuilder().create().fromJson(json, JsonObject.class);
String[] seg = path.split("\.");
for (String element : seg) {
if (obj != null) {
JsonElement ele = obj.get(element);
if (!ele.isJsonObject())
return ele;
else
obj = ele.getAsJsonObject();
} else {
return null;
}
}
return obj;
}
回答by isapir
I'm not sure why this is not built-into Gson, but here is a method that I wrote, which returns a JsonElementgiven a JsonElement input and a JSON Path:
我不确定为什么这不是内置在 Gson 中的,但这是我编写的一个方法,它返回一个JsonElement给定 JsonElement 输入和一个 JSON 路径:
/**
* Returns a JSON sub-element from the given JsonElement and the given path
*
* @param json - a Gson JsonElement
* @param path - a JSON path, e.g. a.b.c[2].d
* @return - a sub-element of json according to the given path
*/
public static JsonElement getJsonElement(JsonElement json, String path){
String[] parts = path.split("\.|\[|\]");
JsonElement result = json;
for (String key : parts) {
key = key.trim();
if (key.isEmpty())
continue;
if (result == null){
result = JsonNull.INSTANCE;
break;
}
if (result.isJsonObject()){
result = ((JsonObject)result).get(key);
}
else if (result.isJsonArray()){
int ix = Integer.valueOf(key) - 1;
result = ((JsonArray)result).get(ix);
}
else break;
}
return result;
}
To call it, use something like:
要调用它,请使用以下内容:
String jsonString = ...;
Gson gson = new Gson();
JsonObject jsonObject = gson.fromJson(jsonString, JsonObject.class);
JsonElement subElement = getJsonElement(jsonObject, "a.b.c[2].d";