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();
我目前正在努力通过改造检索 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();