Android 改造和 GSON : JSON response returns object or string as property value

标签 android kotlin gson retrofit

从服务器返回的 JSON 数据可以返回一个对象,或者如果该对象为空,则返回一个空字符串 ("")。

我的问题是我的 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 做过任何事情 - 所以我希望在正确的方向上得到插入。

谢谢!

最佳答案

最简单的技巧是您可以在类中添加具有相同序列化名称但数据类型为 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 中缺少某些内容,您只会在反序列化对象中得到一个空值。因此,如果存在空字符串,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;
    }

定义反序列化器:

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

关于Android 改造和 GSON : JSON response returns object or string as property value,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48120176/

相关文章:

android - 将 Realm 对象作为 Retrofit 2 PUT 请求主体传递

android - 我如何管理 fragment 堆栈等 Activity

安卓属性动画

android - 如何设置按钮不可见android

lambda - 如何在Kotlin中序列化Lambda

java - GSON 预期为 BEGIN_ARRAY,但实际为 STRING

java - 我在 android 中的应用程序中的屏幕旋转问题?

generics - 如果你只有一个 KClass 对象,用 reified 类型参数调用一个 fun 吗?

spring - Hibernate 并发多对多关系

android - Gson 发布方法