java - 无法使用 GSON 将复杂的 json 序列化为对象?

标签 java json serialization gson

下面是我通过从服务 API 调用返回的 JSON 字符串。为了便于理解,我将其缩短为只有三个 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 响应中,我需要提取 NameClient::SyncreportRecords。这意味着,我只需要从上面的 JSON 响应中提取下面的 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
         }

现在我需要将上面的 reportRecordsClient::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
}

所以序列化后,上面的对象应该看起来像这样 -

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

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

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

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

但由于某种原因,DataMetrics 中的某些字段向我显示了数据,但某些字段为空,这让我认为我的上述代码中有问题或者我的 DataMetrics 类不正确?

最佳答案

通常,对于像 dimensions 这样的嵌套对象,您将为其声明另一个 POJO

class DataMetrics{
  private String min;
  private String max;
  private String avg;
  /*Insert other members*/

  private Dimensions dimensions;

  public boolean isClientSync(){
    return "Client::Sync".equals(dimensions.Name);
  }
  private class Dimensions{
    private String env;
    private String pool;
    private String Name;
  }
}

测试:

 public void test() {

 String json = "[{\"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}]";

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

 Assert.assertTrue(records.get(0).isClientSync());
}

对于percentileMap,您需要一张实际的 map

private Map<String, Integer> percentileMap;

另请注意,成员变量名称应与 JSON 属性名称完全匹配

  • stdDev => stddev
  • 名称 => 名称
  • 百分位数 => percentileMap

关于java - 无法使用 GSON 将复杂的 json 序列化为对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24319284/

相关文章:

java - 将 POST 发送到 Web 服务并验证一些数据并以 JSON 形式发回

json - 难以在关联类型的实例上进行模式匹配

c# - 如何通过匹配值从 JSON 字符串中的特定属性中删除值?

c# - 将没有根对象的json反序列化为c#/vb.net类

c# - 序列化表达式树

java - Guice 会降低我的代码的可读性吗?

java - GWT 序列化 TreeMap 的排序/比较器

serialization - 是否可以在包含对 C 函数的引用的 lua 字节码字符串上调用 loadstring?

java - 如何在一个应用程序中创建 2 个操作栏?

java - 使用 BouncyCaSTLe 在 Java 中验证 ECDSA 签名时出错