com.google.gson.JsonSyntaxException: Ожидался объект com.google.gson.JsonObject, но был получен com.google.gson.JsonNull

Вопрос или проблема

     var retrofitResponse: RetrofitResponse<APIResponse<User>>? = null
        withContext(Dispatchers.IO) {
            retrofitResponse = try {
                val response = BindRetrofitWithService.getServiceInstance(
                    needCustomTimeOut = Config.isChinaBuild(appContext)
                ).registerUser(body, data)
                RetrofitResponse(true, response)
            } catch (e: Exception) {
                RetrofitResponse(false, e.getAPIError())
            }
        }
        return retrofitResponse!!

 fun getServiceInstance(needCustomTimeOut: Boolean = false): APIServices {
        if (GeneralUtils.isNetworkAvailable()) {
            return getRetrofit(needCustomTimeOut).create(APIServices::class.java)
        } else {
            throw NoNetworkException()
        }
    }

 fun getRetrofit(needCustomTimeOut: Boolean = false): Retrofit {

        return getRetrofitObject(
            null, if (needCustomTimeOut) {
                CHINA_FILE_UPLOAD_CONNECT_TIME_OUT
            } else {
                CONNECT_TIME_OUT
            }else {
                WRITE_TIME_OUT
            }
        )
    }

    /**
     * Создание пользовательского экземпляра Retrofit
     */
    private fun getRetrofitObject(
        headers: HashMap<String, String>?,
        connectionTimeOut: Long,
        readTimeOut: Long,
        writeTimeOut: Long
    ): Retrofit {
        val loggingInterceptor = HttpLoggingInterceptor()
        loggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
        val okHttpClient = OkHttpClient.Builder()
        //okHttpClient.addInterceptor(MockInterceptor())
        okHttpClient.addInterceptor { chain -> 
            //if(GeneralUtils.isNetworkAvailable()){
            val оригинал = chain.request()
            val requestBuilder = оригинал.newBuilder()
            if (headers != null && headers.size > 0) {
                for ((key, value) in headers) {
                    requestBuilder.addHeader(key, value)
                }
            }
            val request = requestBuilder.build()
            return@addInterceptor chain.proceed(request)

            /*}else{
                throw NoNetworkException()
            }*/
        }
        okHttpClient.addInterceptor(loggingInterceptor)
        okHttpClient.connectTimeout(connectionTimeOut, TimeUnit.SECONDS)
        okHttpClient.readTimeout(readTimeOut, TimeUnit.SECONDS)
        okHttpClient.writeTimeout(writeTimeOut, TimeUnit.SECONDS)

        return Retrofit.Builder()
            .baseUrl(Config.getRetrofitBaseUrl(UCHContext.getAppContext()))
            .addConverterFactory(GsonConverterFactory.create(GsonBuilder().create()))
            .client(okHttpClient.build())
            .build()
    }

класс модели пользователя
 @SerializedName(DBConstants.COL_USER_PROFILE_NOTE)
    @ColumnInfo(name = DBConstants.COL_USER_PROFILE_NOTE)
    @Nullable
    public String note = null;

    @SerializedName(DBConstants.COL_USER_PROFILE_TITLE)
    @ColumnInfo(name = DBConstants.COL_USER_PROFILE_TITLE_VAL)
    @Nullable
    public String titled = null;
    @SerializedName(DBConstants.COL_USER_PROFILE_ADDRESSES)
    @ColumnInfo(name = DBConstants.COL_USER_PROFILE_ADDRESSES)
    @Nullable
    public JsonObject addresses= new JsonObject();

Примечание:
иногда “addresses”:null приводит к следующей ошибке
#com.google.gson.JsonSyntaxException: Ожидался com.google.gson.JsonObject, но был com.google.gson.JsonNull; на пути
$.data.addresses
#responseCode= 1208, responseCodeMessage= Сбой API, userMessage= Что-то пошло не так, пожалуйста, попробуйте снова.
как решить эту проблему? Я пробовал пользовательский и стандартный классы Gson, но это не помогло.

Ответ или решение

Ошибка com.google.gson.JsonSyntaxException: Expected a com.google.gson.JsonObject but was com.google.gson.JsonNull возникает, когда ваш код ожидает, что поле addresses должно быть объектом JsonObject, но фактически оно приходит как null. Чтобы устранить эту проблему, вы можете применить несколько подходов.

1. Изменение модели данных

Вместо того чтобы использовать JsonObject для поля addresses, вы можете использовать Object и обрабатывать его как null. Это делается для того, чтобы Gson мог корректно десериализовать null:

@SerializedName(DBConstants.COL_USER_PROFILE_ADDRESSES)
@ColumnInfo(name = DBConstants.COL_USER_PROFILE_ADDRESSES)
@Nullable
public Object addresses = null;  // Измените JsonObject на Object

2. Создание кастомного десериализатора

Если вам необходимо продолжать использовать JsonObject (например, когда вам нужно проводить операции с объектом), вы можете написать кастомный десериализатор:

public class UserDeserializer implements JsonDeserializer<User> {
    @Override
    public User deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        JsonObject jsonObject = json.getAsJsonObject();
        User user = new User();

        user.note = jsonObject.get(DBConstants.COL_USER_PROFILE_NOTE).getAsString();
        user.titled = jsonObject.get(DBConstants.COL_USER_PROFILE_TITLE).getAsString();

        // Проверяем, есть ли поле addresses и не является ли оно null
        JsonElement addressesElement = jsonObject.get(DBConstants.COL_USER_PROFILE_ADDRESSES);
        if (addressesElement != null && !addressesElement.isJsonNull()) {
            user.addresses = addressesElement.getAsJsonObject();
        } else {
            user.addresses = new JsonObject(); // Или null, в зависимости от того, что вам нужно
        }

        return user;
    }
}

Затем зарегистрируйте десериализатор в вашей конфигурации Gson:

Gson gson = new GsonBuilder()
        .registerTypeAdapter(User.class, new UserDeserializer())
        .create();

3. Обработка ответа в коде

При выполнении вызова API необходимо также убедиться, что вы правильно обрабатываете null значения после получения ответа:

val response = BindRetrofitWithService.getServiceInstance(...)
response?.let {
    if (it.data.addresses == null) {
        // Обработка случая, когда addresses равно null
        // Например, инициализация пустого JsonObject
        it.data.addresses = JsonObject()
    }
}

4. Изменение API, если возможно

В идеале, если возможно, корректируйте серверную часть, чтобы она возвращала объект JSON вместо null. Например, вместо того чтобы возвращать:

{
    "addresses": null
}

Сервер должен возвращать:

{
    "addresses": {}
}

Заключение

Каждое из предложенных решений подходит для разных сценариев. Вы можете выбрать самое подходящее для вашей ситуации. Если есть возможность изменить API — это самый надежный способ. Если API не поддается изменению, используйте кастомные десериализаторы или корректируйте обработку на клиенте. Таким образом, ваша программа будет готова к правильной обработке null полей без сбоев.

Оцените материал
Добавить комментарий

Капча загружается...