如何使用GSON迭代JSON数组并从中提取每个JSON对象?

时间:2014-06-17 07:06:20

标签: java json gson arrays jsonobject

下面是我的JSON字符串,我通过从服务API调用回来。为了理解目的,我只有三个reportRecords缩短了它。一般来说,它可能有~500 reportRecords

{
   "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响应中,我需要提取reportRecordsName的{​​{1}}。这意味着,我只需从上面的JSON响应中提取Client::Sync以下。

reportRecords

现在我需要将         {             "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          } 上面的reportRecords解析为以下对象 -

Client::Sync

上面的变量,像这样的地图 -

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
}

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

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

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

4 个答案:

答案 0 :(得分: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并只转换必要的对象(但我怀疑这实际上会比上面描述的更快)。

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

<强>更新

同样适用于java 7:

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

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

答案 1 :(得分: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"));

答案 2 :(得分: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));
   }
}

但我不认为这实际上比第一个更快,因为在这两种情况下你都是用解析器将json转换为java函数对象并获取JsonArray或其他任何东西。考虑到两者都是Googles libs的事实,我假设使用gson从JsonObject解析到某个特定类型比从String(原始json)解析到相同的特定类型...

答案 3 :(得分:-1)

我没有尝试过,但它可能会奏效。

 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));
             }
         }

//// public Object getClassFromJsonObject(JSONObject json,Class 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);
}