Retrofit 将未知字段作为 Map

Retrofit get unknown fields as Map

我目前正在努力通过改造检索 JSON 对象。问题是,我事先不知道字段的名称。通常我会将这些字段映射为 Map,但是如何命名这个改造对象?

这就是我的 JSON 对象的样子:

{
    "User{email='john.doe@example.com', id='JDoe'}" : {
        "101" : 1,
        "102" : 2,
        "103" : 3,
        "104" : 2
     },
     "User{email='jane.doe@example.com', id='JDoe01'}" : {
         "101" : 3,
         "102" : 1,
         "103" : 1,
         "104" : 3
     }
}

改造对象class:

public static class UserSettings{
    public Map<String, Map<String, Integer>> settingsMap;
}

现在我认为发生的事情是改造试图找到一个名为 'settingsMap' 的对象。但是这个映射是根元素,因此没有名称,所以 settingsMap 是一个空对象。

感谢任何解决此问题的帮助!

提前致谢。

您必须为 UserSettings 对象实现自己的反序列化器。如下图:

首先为用户设置数据创建模型:

public class UserSettings {
        public Map<String, Map<String, Integer>> settingsMap;

    public  UserSettings(){
        settingsMap = new HashMap<>();
    }

    public void add(String key, Map<String, Integer> settingMap){
        settingsMap.put(key, settingMap);
    }
}

下一步为您对象准备API客户端

public interface UserSettingApiClient {

    @GET("/yourEndpoint")
    UserSettings getUserSetting();
}

现在是最重要的一步。您必须创建自己的 JsonDeserializer,如下所示:

public class UserDeserializer implements JsonDeserializer<UserSettings> {

    @Override
    public UserSettings deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        UserSettings userSettings = new UserSettings();
        JsonObject jsonObject = (JsonObject) json;
        for (Map.Entry<String, JsonElement> element : jsonObject.entrySet()){
            String key = element.getKey();
            JsonObject obj = jsonObject.getAsJsonObject(key);
            Map<String, Integer> settingMaps = new HashMap<>();
            for (Map.Entry<String, JsonElement> setting : obj.entrySet()){
                String settingKey = setting.getKey();
                Integer integer = obj.get(settingKey).getAsInt();
                settingMaps.put(settingKey, integer);
            }
            userSettings.add(key,settingMaps);
        }
        return userSettings;
    }
}

执行此操作时,您必须在 GsonConverter 中注册此解串器。下面的示例显示了如何调用完整的请求,但您必须在创建 RestAdapter

的地方使用此解决方案
new RestAdapter.Builder()
       .setEndpoint("http://your.apiaddress.com")
       .setLogLevel(RestAdapter.LogLevel.FULL)//this is not necessary 
       .setConverter(
              new GsonConverter(
                   new GsonBuilder()
                             .registerTypeAdapter(UserSettings.class, new UserDeserializer())
                   .create()))
      .build()
      .create(UserSettingApiClient.class)
      .getUserSetting();