2017-02-11 175 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