从服务器返回的JSON数据可以返回一个对象,或者如果该对象为null,则返回一个空字符串(“”)。
我的问题是我的DTO需要一个对象,但它会看到一个字符串并崩溃。
PersonDTO
data class PersonDto(
@SerializedName("firstName") val first: String,
@SerializedName("lastName") val last: String,
@SerializedName("favorites") val favorites: FavoriteDto,
)
FavoriteDto
class FavoriteDto(
@SerializedName("color") val color: String,
@SerializedName("number") val number: Int
)
来自服务器的不同回复
"person" : {
"firstName": "Steve",
"lastName" : "Johnson",
"favorites" : {
"color": "Purple",
"number": 25
}
}
...
"person" : {
"firstName": "Steve",
"lastName" : "Johnson",
"favorites" : ""
}
我听说我可能需要一个自定义的GSON解串器,但除了开箱即用之外我从未对GSON做任何事情 - 所以我希望能朝着正确的方向轻推。
谢谢!
答案 0 :(得分:3)
最简单的黑客是你可以在类中添加具有相同序列化名称但具有String数据类型的额外字段。像这样 -
data class PersonDto(
@SerializedName("firstName") val first: String,
@SerializedName("lastName") val last: String,
@SerializedName("favorites") val favorites: FavoriteDto,
@SerializedName("favorites") val favoritesStr: String,
)
由于Gson中没有任何内容作为“必需”字段,如果JSON中缺少某些内容,您将在反序列化对象中获得null。因此,如果有一个空字符串,那么FavoriteDto对象将为null,否则为null。
修改强>
我正在添加一些我之前编写过的Java代码。这可能会有所帮助:
public class PersonDto {
private FavoriteDto favorites;
private String favoritesStr;
public FavoriteDto getResponseDataObject() {
return favorites;
}
public void setResponseDataObject(FavoriteDto favorites) {
this.favorites = favorites;
}
public String getResponseDataString() {
return favoritesStr;
}
public void setResponseDataString(String favoritesStr) {
this.favoritesStr = favoritesStr;
}
定义Deserializar:
public static class ArrayObjectDualityDeserializer implements JsonDeserializer<PersonDto> {
public PersonDto deserialize(JsonElement json, Type typeOfT,
JsonDeserializationContext context) throws JsonParseException {
PersonDto response = new PersonDto();
JsonObject object = json.getAsJsonObject();
if(object.get("favorites").isJsonArray()) {
} else if(object.get("favorites").isJsonObject()) {
try {
FavoriteDto dtoObject = gson.fromJson(object.get("favorites"), FavoriteDto.class);
response.setResponseDataObject(dtoObject);
} catch (JsonSyntaxException e) {
DebugLogger.e("Error " + e);
}
} else if (object.get("favorites").isJsonNull()) {
} else {
response.setResponseDataString(object.get("favorites").getAsString());
}
}
}
和
public static Gson gson = new GsonBuilder()
.registerTypeAdapter(PersonDto.class, new ArrayObjectDualityDeserializer())
.create();
最后:
private static Retrofit retrofit = null;
private static OkHttpClient.Builder httpClient = null;
private static OkHttpClient session_client = null;
httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(new SessionOkHttpInterceptor());
session_client = httpClient.build();
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(session_client)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
答案 1 :(得分:0)
@Subrato M.的回答是部分正确的。为了工作,您应该从两个字段中删除@SerializedName("favorites")
注释才能工作。在这种情况下,Gson
在反序列化名为favorites
的多个json字段时不会抛出错误,因为您没有任何使用该名称注释的字段(也不要注明名称) fileds与预期字段名称相同beucase Gson
将尝试反序列化)。使用自定义反序列化程序检查是对象还是字符串。
答案 2 :(得分:0)
现在不需要@Subrato M的破解,您不会得到正确的json,因为您缺少class FavoriteDto
之前的data关键字,这就是为什么get和set方法不存在>