2014-06-17 117 views
2

下面是我通过从服务API调用回来的JSON字符串。为了理解目的,我只用了三个reportRecords来缩短它。一般情况下,它可能有5〜50 reportRecords如何迭代JSON数组并使用GSON从中提取每个JSON对象?

{ 
   "aggRecords": { 
      "reportRecords": [ 
         { 
            "min": 0, 
            "max": 12, 
            "avg": 0.3699187, 
            "count": 246, 
            "sumSq": 571, 
            "stddev": 1.4779372, 
            "median": 0, 
            "percentileMap": { 
               "95": 4 
            }, 
            "metricName": "TransactionDuration", 
            "dimensions": { 
               "env": "dev", 
               "pool": "titan", 
               "Name": "PostProcessing", 
               "Type": "PostProcessing" 
            }, 
            "value": 91 
         }, 
         { 
            "min": 0, 
            "max": 23, 
            "avg": 2.3991289E-4, 
            "count": 1463031, 
            "sumSq": 3071, 
            "stddev": 0.045814946, 
            "median": 0, 
            "percentileMap": { 
               "95": 0 
            }, 
            "metricName": "TransactionDuration", 
            "dimensions": { 
               "env": "dev", 
               "pool": "titan", 
               "Name": "ResourceContext", 
               "Type": "ResourceContext" 
            }, 
            "value": 351 
         }, 
         { 
            "min": 0, 
            "max": 1209, 
            "avg": 1.9203402, 
            "count": 7344636, 
            "sumSq": 71832774, 
            "stddev": 2.4683187, 
            "median": 2, 
            "percentileMap": { 
               "95": 4 
            }, 
            "metricName": "TransactionDuration", 
            "dimensions": { 
               "env": "dev", 
               "pool": "titan", 
               "Name": "Client::Sync", 
               "Type": "Client::Sync" 
            }, 
            "value": 14104200 
         } 
      ] 
   }, 
   "minRecordsMap": {} 
} 

现在从上面的JSON响应,我需要提取reportRecordsNameClient::Sync。意思是,我只需要从上面的JSON响应中提取低于reportRecords

​​

现在我需要为Client::Sync上述reportRecords解析以下对象 -

public class DataMetrics { 

    private String pool; 
    private String name; 
    private String type; 
    private String env; 
    private String metricName; 
    private String percentile; 
    private String median; 
    private String stdDev; 
    private String sumSq; 
    private String count; 
    private String avg; 
    private String max; 
    private String min; 

    // getters and setters here 
} 

以上变量,映射这样的 -

pool is titan 
name is Client::Sync 
type is Client::Sync 
env is dev 
metricNname is TransactionDuration 
95th percentile is 4 
median is 2 
stdDev is 2.4683187 
sumSq is 71832774 
count is 7344636 
avg is 1.9203402 
max is 1209 
min is 0 

我使用GSON库这里下面是我到目前为止所尝试的 -

private static RestTemplate restTemplate = new RestTemplate(); 

public static void main(String[] args) { 

    String jsonLine = restTemplate.getForObject("some_url", String.class); 
    System.out.println(jsonLine); // here jsonLine will give me above big JSON String 

    JsonElement jelement = new JsonParser().parse(jsonLine); 
    JsonObject jobject = jelement.getAsJsonObject(); 
    jobject = jobject.getAsJsonObject("aggRecords"); 
    JsonArray jarray = jobject.getAsJsonArray("reportRecords"); 

    // now how do I iterate JsonArray and get each JSON object 
    // and then check "name" property of each object, if "Client::Sync" found, read that object for all properties 
    // and set it using setters. 

} 

现在我无法理解如何迭代JsonArray并从中提取每个JSON对象?

+0

@hexin我正在GSON和我想上面的例子不使用GSON。 – john

+0

对不起,我的失败:/ – hexin

回答

3

所以,你必须与你的记录JsonArray对象,这里是你做了什么让你的功能对象:

Type type = new TypeToken<List<DataMetrics>>() {}.getType(); 
List<DataMetrics> records = gson.fromJson(jsonArrayThatYouHave, type); 

然后你遍历你的对象和筛选你需要的。 在java中8,你可以这样做:

List<DataMetrics> result = records.stream().filter(record -> record.name.equals("Client::Sync")).collect(toList()); 

这种方法是将所有的对象和之后的迭代,如果代码恰好这部分的性能很关键,你仍然可以通过JSON遍历并转换只需要对象(但我怀疑这实际上比上面描述的要快)。

无论如何,这是更易于维护和易于理解的代码。

UPDATE:

对Java 7同样会:

List<DataMetrics> result = new LinkedList<>(); 

for(DataMetrics record : records){ 
    if(record.name.equals("Client::Sync")){ 
     result.add(record); 
    } 
} 
+0

谢谢Vach。我将如何在Java7中做到这一点?截至目前,我正在使用Java7。 – john

+0

@ user2809564检查更新 – vach

+0

感谢您的帮助。我试过这个,不知怎的,大部分字段都像百分位,姓名,类型,分数和其他几个字符一样空,但有些字段有数据。你看到有什么不对吗? – john

0

您可能要解析的所有对象,然后筛选你感兴趣的那些

你已经获得jArray后,尝试:

//get json array from json string 
JsonArray jarray = jobject.getAsJsonArray("reportRecords"); 

//get a list of reportRecords using Gson 
Gson mGson = new Gson(); 
Type listType = new TypeToken<List<DataMetrics>>(){}.getType(); 
List<DataMetrics> dataMetricsList = mGson.fromJson(reportRecordsJsonArray, listType); 

//Filter only the ones with a specific name 
List<DataMetrics> dataMetricsFilteredList = dataMetricsList.stream().filter(dataMetric -> dateMetric.getName.equals("Client::Sync")); 
0

我没有尝试但它可能工作。

public void getFromJson(JSONObject json) 
     { 
      JSONArray jarray = (JSONArray) json.get("reportRecords"); 
      List<DataMetrics> myList = new ArrayList(); 
      for(int i = 0; i < jarray.size(); i++) 
      { 
       myList.add((DataMetrics) getClassFromJsonObject((JSONObject) jarray.get(i), 
DataMetrics.class)); 
      } 
     } 

//// 公共对象getClassFromJsonObject(JSON的JSONObject,MyClass类){

Object object = new Object(); 
    ObjectMapper obj = JSONMapperFactory.createMapper(); 
    obj.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 
    try { 
     object = obj.readValue(json.toString(), myClass); 
    } catch (IOException e) { 
     e.printStackTrace(); 
     throw new RuntimeException(e); 
    } 
    return myClass.cast(object); 
} 
0

或者,如果你想要遍历JSON和分析,才需要那些继承人,你可以做什么:

Type type = new TypeToken<List<DataMetrics>>() {}.getType(); 

for(JsonElement elem : jsonArrayThatYouHave) { 
    if (elem.getAsJsonObject().get("name").getAsString().equals("Client::Sync")) { 
     result.add(gson.fromJson(elem, type)); 
    } 
} 

但我不认为这实际上比第一个更快,因为在这两种情况下,你正在使用解析器和gettin将json转换为java功能对象g JsonArray或其他任何东西。考虑到两者都是谷歌库的事实,我假设从JsonObject解析到某种特定类型的Gson比从字符串(原始JSON)到相同的特定类型的方式更快...