Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用带有路径的Gson_Java_Json_Gson_Jsonpath - Fatal编程技术网

Java 使用带有路径的Gson

Java 使用带有路径的Gson,java,json,gson,jsonpath,Java,Json,Gson,Jsonpath,使用简单的Json文件,例如: {"menu": { "id": "file", "value": "File", "popup": { "menuitem": [ {"value": "New", "onclick": "CreateNewDoc()"}, {"value": "Open", "onclick": "OpenDoc()"}, {"value": "Close", "onclick": "CloseDoc()"} ]

使用简单的Json文件,例如:

{"menu": {
  "id": "file",
  "value": "File",
  "popup": {
    "menuitem": [
      {"value": "New", "onclick": "CreateNewDoc()"},
      {"value": "Open", "onclick": "OpenDoc()"},
      {"value": "Close", "onclick": "CloseDoc()"}
    ]
  }
}}
我希望能够使用以下路径获取名为
menuitem
JsonArray

String path =  "menu.popup.menuitem"
我尝试使用以下方法进行此操作:

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
}
与:

但是当我尝试
isJsonArray()
时,返回值是
false
。当使用
Gson.toJson(jsonElement)
执行额外的健全性检查时,输出是最初输入的完整json字符串(如上)。
出什么问题了?

split
使用正则表达式查找应该拆分字符串的位置,但正则表达式中的
是一个特殊字符,表示“行分隔符旁边的任何字符”,这意味着您实际上在拆分每个字符。所以对于弦状的

"foo"
“foo”。拆分(“.”
将在
f
o
o

"foo"
 ^^^
这意味着您将得到带有四个空字符串的结果数组(3次拆分得到4个元素)

实际上,我在这里撒谎是因为
split(regex)
做了一件额外的事情:它从结果数组中删除尾随的空字符串,但数组只包含空字符串,这意味着它们都将被删除,因此
split(“.”
将只返回空数组
[]
,这样循环就不会迭代一次(这就是为什么您的方法返回未修改的
obj

要解决此问题,您需要将
转换为文字(您需要对其进行转义)。为此,您可以使用例如
split(\\”)
split([.]”)
split(Pattern.quote(“.”
,其工作原理与
split(\\Q.\\E”)
相同-它添加了引号区域

同样,在循环内部,您应该首先检查正在处理的Json类型,因为如果Json是数组,则
getAsJsonObject
将失败

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;
}

我不确定为什么这没有内置到Gson中,但我编写了一个方法,它返回给定的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;
}
要调用它,请使用以下内容:

String jsonString = ...;

Gson gson = new Gson();
JsonObject  jsonObject = gson.fromJson(jsonString, JsonObject.class);
JsonElement subElement = getJsonElement(jsonObject, "a.b.c[2].d";

可能重复使用,例如,
而不是
。或者,path.split([.]])也可以用作[]中包含的文字character@prash是的,答案中已经提到了这一点,还有其他几种方式:)哇,太详细了!抱歉,我注意到我刚刚检查了代码部分..ty指出:-)它没有烘焙到Gson中,因为有一种单独的、更正式的方式来完成它,称为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;
}
String jsonString = ...;

Gson gson = new Gson();
JsonObject  jsonObject = gson.fromJson(jsonString, JsonObject.class);
JsonElement subElement = getJsonElement(jsonObject, "a.b.c[2].d";