2014-06-17 98 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)到相同的特定類型的方式更快...