2017-02-11 182 views
1

比方說,我有一個文件sample.json,其中包含一個如下所示的對象數組。使用Streaming API和Json解析器進行JSON解析 - 混合模式

[ {Name: "ABC", "email" : "[email protected]", "city" : "NewYork"}, {Name: "XYZ", "email" : "[email protected]", "city" : "NewJersey"}] 

我正在使用TestNG框架和GSON庫來解析JSON。

下面是我想要解析JSON對象的類。我的目標是通過數組中的名稱過濾對象並僅返回該對象。 我正在使用Streaming API來避免一次出現在json文件中的所有數據。

public class JSON{ 

private JsonObject jsonObject; 

@Test 
public void readJSON(){ 
    getJSONObject("C:\\..\\sample.json", "ABC"); 
    readData("email"); 
} 

public JsonObject getJSONObject(fileName, Name){ 
JsonReader jsonReader = new JsonReader(new FileReader(fileName)); 
jsonReader.beginArray(); 
while (jsonReader.hasNext()){ 
    str = jsonReader.nextString(); 
    If (str.equals(Name)){ 
      System.out.println("Found Name"); 
      // To get the object - we can use fromJson(jsonReader, Person.class), 
      // where Person.class defines all the json variables as class variables.   
      // But I want to use JsonParser or something like that to return just this object which has the Name "ABC" 

     } 
    } 
} } 

原因,我不希望創建一個Person類,並使用fromJSON因爲我使用此功能對不同類型的JSON字符串。所以我不喜歡爲不同的字符串創建不同的類。我想使用其他的東西,只是返回所需的對象。另外我不確定如何使用Streaming API方法的hasNext()遍歷數組來查找所需的對象。

任何輸入讚賞。謝謝。

+0

http://stackoverflow.com/questions/23698415/how-to-filter-json-array-in-c-sharp – Nothing

回答

1

我不推薦使用流式API,使用起來真的很痛苦。但在你想要從數組中提取一個對象的情況下,這是可能的。

JsonReader reader = new JsonReader(new StringReader(
      "[ {Name: \"ABC\", \"email\" : \"[email protected]\", \"city\" : \"NewYork\"}, {Name: \"XYZ\", \"email\" : \"[email protected]\", \"city\" : \"NewJersey\"}]\n")); 


    String target = "ABC"; 

    ArrayList<String> names = new ArrayList<String>(); 

    reader.setLenient(true); 
    reader.beginArray(); 
    while(reader.hasNext()) { 
     reader.beginObject(); 
     // peek is your best friend in this world, as it tells you what object you're looking at 
     while(reader.peek() != JsonToken.END_OBJECT) { 
      if(reader.peek() == JsonToken.NAME) { 
       String name = reader.nextName(); 
       if(name.equals("Name")) { 
        if(reader.nextString().equals(target)) { 
         // I'm just printing these out right now but you could construct an object and set variables instead. 
         while(reader.peek() == JsonToken.NAME) { 
          switch (reader.nextName()) { 
           case "email": 
            System.out.println("Found email for " + target + " " + reader.nextString()); 
            break; 
           case "city": 
            System.out.println("Found city for " + target + " " + reader.nextString()); 
            break; 

          } 
         } 
        } 

       } 
      } 
      //this is really the key to the parser which is to skip all the values that you're not interested in 
      reader.skipValue(); 
     } 


     reader.endObject(); 
    } 
    reader.endArray(); 
} 
+0

謝謝你的回答。我是Java&Json的新手。我想使用Streaming API的唯一原因是json文件最終可能會有大量的testdata,我可能只需要其中的幾行來執行當前的執行。所以我不想馬上把它們都收回來。我的目標是獲取所需的對象並將其分配給我的類中的JsonObject類型的公共變量,並使用此對象通過此類語法在另一個函數中檢索值(電子郵件,城市) - JsonObject.get(「email」)的ToString。那麼是否有可能只從你的函數返回該對象? – newuser

+0

只需從電子郵箱中返回,即可返回想要的內容,避免掃描任何不需要的內容。你也可以避開開關,只使用if(「email」.equals(reader.nextName()){return reader.nextString();} – linead

+0

如果我想在另一個函數中獲得一個函數和城市的電子郵件,通過閱讀器迭代並驗證它是否匹配Name =「ABC」這兩個時間,正確的。我認爲通過迭代一個單一時間將數組中的元素作爲JsonObject返回,並在稍後使用get方法檢索值。不能從該函數返回該對象,並且Streaming API已經實現了通過令牌來迭代令牌 – newuser

2

第三方庫

如果你沒有資源/性能問題,加載整個JSON文檔,我建議JsonPath給你類似XPath的訪問挑選出你想要的比賽。

但是,我假設你想流Json數據,因爲它會導致你真正測量過的實際問題。有一些談論有streaming extension for JsonPath,但我沒有經驗。

這讓我想到了可以使用的其他替代方法,並且我遇到了the stoppable parser in JsonSurfer,看起來它可能會解決您的問題。

推出自己的

我開始使用你原來的問題給你寫一段代碼,但我發現自己不得不創建每個Person類爲我流的JSON,這似乎是你正在嘗試避免。讓我知道,如果你想堅持一個「滾動你自己」的方法,而不是我提到的第三方庫。

我用這個職位Gson streaming tutorial來幫助我理解如何在流媒體時解析Json標記。

+0

JsonPath是如果性能是不是正在考慮很方便。謝謝你讓我知道。 – newuser