2014-09-28 101 views
3

使用一個簡單的JSON文件,例如:使用GSON與路徑

{"menu": { 
    "id": "file", 
    "value": "File", 
    "popup": { 
    "menuitem": [ 
     {"value": "New", "onclick": "CreateNewDoc()"}, 
     {"value": "Open", "onclick": "OpenDoc()"}, 
     {"value": "Close", "onclick": "CloseDoc()"} 
    ] 
    } 
}} 

我希望能夠使用路徑來獲取JsonArray命名爲menuitem

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 
} 

有:

JsonElement jsonElement = fromString(json, path); 

但是,當我嘗試isJsonArray()返回值是false。當使用Gson.toJson(jsonElement)進行額外的完整性檢查時,輸出是最初輸入的完整json字符串(上圖)。 怎麼回事?

+0

可能重複 「」 (點)](http://stackoverflow.com/questions/14833008/java-string-split-with-dot) – Devrim 2014-09-28 18:03:08

+0

使用,例如';'而不是'.'。 – 2014-09-28 18:12:20

回答

3

split使用正則表達式來找到哪個字符串應該被拆分的地方,但在.正則表達式是特殊字符代表「行分隔符旁邊的任何字符」,這意味着你實際上是在分裂的每個字符。因此,對於字符串如

"foo" 

"foo".split(".")將各執foo

"foo" 
^^^ 

這意味着你將得到的結果數組有四個空字符串(3個拆分給4種元素)。

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

其實我撒謊了這裏,因爲split(regex)做一件其他的東西:它刪除尾隨結果數組空字符串,但您的陣列只包含空字符串,這意味着它們將全部被刪除,所以split(".")將僅返回空array []所以你的循環不會迭代一次(這就是爲什麼你的方法返回未修改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; 
} 
+0

或者path.split(「[。]「)也可以用作封閉在[]中描述一個文字字符 – prash 2017-09-21 09:51:45

+0

@prash是的,這已經在答案中提到,以及其他一些方法:) – Pshemo 2017-09-21 12:08:16

+0

哇這樣一個詳細的一個,它是!..對不起,我dint注意我剛剛檢查了代碼部分.. ty指出:-) – prash 2017-09-21 12:12:05

2

我不知道這是爲什麼不內置到GSON,但這裏是我寫的一個方法,它返回給定JsonElement輸入和JSON路徑一JsonElement

/** 
* 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"; 
[Java字符串分割與