Using Gson with a path

若如初见. 提交于 2019-12-04 11:17:09

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

"foo"

"foo".split(".") will split on f, o, o

"foo"
 ^^^

which means you will get as result array with four empty strings (3 splits give 4 elements).

["", "", "", ""]

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).

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.

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

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

I'm not sure why this is not built-into Gson, but here is a method that I wrote, which returns a JsonElement given a JsonElement input and a JSON Path:

/**
 * 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";
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!