【问题标题】:How to parse a nested map using GSON如何使用 GSON 解析嵌套地图
【发布时间】:2014-08-06 15:06:04
【问题描述】:

我正在尝试解析具有以下格式的 JSON 字符串:

  { 
      "request" : { 
          "Format" : "json",
          "Method" : "method",
          "NetworkId" : "net",
          "NetworkToken" : "token",
          "Service" : "service",
          "Target" : "target",
          "Version" : "2"
      },
      "response" : { 
          "data" : { 
              "1315" : { 
                  "AffiliateUser" : { 
                      "id" : "1315" 
                  } 
              } 
          },
          "errorMessage" : null,
          "errors" : [  ],
          "httpStatus" : 200,
          "status" : 1
      }
}

使用此代码:

public class AffiliateIdResponse{
    private Map<String, Map<String, Map<String, Map<String, String>>>> data;

    public static AffiliateIdResponse fromJson(String jsonString) {
        Type mapType = new TypeToken<Map<String, Map<String, Map<String, Map<String, String>>>>>() {
        }.getType();
        GsonBuilder gsonBuilder = new GsonBuilder();
        gsonBuilder.registerTypeAdapter(mapType, new Gson().getAdapter(TypeToken.get(mapType)));
        return gsonBuilder.create().fromJson(jsonString, AffiliateIdResponse.class);
    }

    public static AffiliateIdResponse handleResponse(MyHttpResponse httpResponse) {
        AffiliateIdResponse response = null;
        if (httpResponse.getStatusCode() == MyHttpStatus.OK
                || httpResponse.getStatusCode() == MyHttpStatus.ACCEPTED
                || httpResponse.getStatusCode() == MyHttpStatus.CREATED) {
            response = fromJson(httpResponse.getBody());
        } else {
        response = new AffiliateIdResponse();
        }
        response.setHttpResponseData(httpResponse);
        return response;
    }
}

但名为 data 的字段始终为空。如果我改为这样做:

public class AffiliateIdResponse{
    public static AffiliateIdResponse fromJson(String jsonString) {
        Type mapType = new TypeToken<Map<String, Map<String, Map<String, Map<String, String>>>>>() {
        }.getType();
        Map<String, Map<String, Map<String, Map<String, String>>>> map = null;
        map = new Gson().fromJson("{ \"data\": { \"1315\": { \"AffiliateUser\": {" +
                    "\"id\":\"1315\"}}}}", mapType);
    }

    public static AffiliateIdResponse handleResponse(MyHttpResponse httpResponse) {
        AffiliateIdResponse response = null;
        if (httpResponse.getStatusCode() == MyHttpStatus.OK
                || httpResponse.getStatusCode() == MyHttpStatus.ACCEPTED
                || httpResponse.getStatusCode() == MyHttpStatus.CREATED) {
            response = fromJson(httpResponse.getBody());
        } else {
        response = new AffiliateIdResponse();
        }
        response.setHttpResponseData(httpResponse);
        return response;
    }
}

名为 map 的值实际上将包含我想要的数据。为什么使用第一种方法时这不起作用?

【问题讨论】:

  • 你能和我们分享一下 AffiliateIdResponse 对象吗?
  • @Leo 我认为这并不重要,因为 json 解析是在 fromJson 方法中完成的,但我已经更新为包含整个类。

标签: json types map gson


【解决方案1】:

在您的第二个示例中,您已将反序列化的“可见性”降低到由

表示的 4 层数据
  1. 数据
  2. 1315
  3. 附属用户
  4. 身份证

因此,反序列化过程将每一层作为键映射到键值对中,值是下一层映射。您记录到控制台的输出显示为

{data={1315={AffiliateUser={id=1315}}}}

在您的第一个示例中,没有迹象表明您尝试解析的 json 的可见性级别,因此我假设您正在传递整个字符串。因此,您还没有“告诉”反序列化过程如何通过您的实现“逐步”通过结构。

如果你传入的是整个json结构,那么下面会提取信息

class ResponseContainer {

    private Response response;

    class Response {
         private Map<String, Map<String, Map<String, String>>> data;
         private Integer status;

         public String toString(){
          return "{data : " + data.toString() +"}, status: " + status + "}";
         }
    }

    public ResponseContainer fromJson(String jsonString) {
        new Gson().fromJson(jsonString, ResponseContainer.class);
    }

    public String toString(){
        return response.toString();
    }
} 

输出:{data : {1315={AffiliateUser={id=1315}}}}, status: 1}

如果这是自定义反序列化链的一部分,其中 jsonString 参数是较大数据结构的子序列,那么“为什么”很可能是由于反序列化过程 -> 结构关系的错位。

【讨论】:

  • 第一个代码块中传入 fromJson 的值 jsonString 确实包含整个 json 响应。我在另一个响应类中做了同样的事情,其中​​数据只是一个布尔值,我能够很好地解析它。也许这不正确,但我认为同样的过程可以在这里处理数据对象。
  • 我认为使用我采用的方法不需要typeAdapter。再看一遍,默认的地图处理程序将使用简单的new Gson().fromJson() 解析出数据。大多数情况下,默认的反序列化行为就足够了。
  • 好的,所以我使用了这种方法,并且能够提取数据对象的嵌套映射。我仍然不确定为什么另一个响应类只有一个布尔数据字段并且它正在正确解析该数据值但它不会在它的映射时。
  • 仅供参考:类型适配器不是必需的,我写的和你一样。
  • 所以我发现我的结构从来没有工作过,我总是需要解析出“响应”部分。因为我使用的是布尔值,所以它总是默认为 false。
猜你喜欢
  • 1970-01-01
  • 2013-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多