¿Por qué gson no puede convertir esto correctamente?

Tengo el siguiente objeto en una cadena json:

{
  "links": {},
  "apiResponseInfo": null,
  "id": "6a88e822-d0dd-41be-be05-da8e55b99501",
  "actionId": null,
  "amount": 0,
  "currency": null,
  "approved": false,
  "status": "Declined",
  "authCode": "auth code",
  "responseCode": "30041",
  "responseSummary": "Card is lost/stolen",
  "threeDS": null,
  "risk": null,
  "source": {
    "id": "src_321435425",
    "type": "card",
    "billingAddress": null,
    "phone": null,
    "expiryMonth": 0,
    "expiryYear": 0,
    "name": null,
    "scheme": null,
    "last4": null,
    "fingerprint": null,
    "bin": null,
    "cardType": null,
    "cardCategory": null,
    "issuer": null,
    "issuerCountry": null,
    "productId": null,
    "productType": null,
    "avsCheck": "D",
    "cvvCheck": null,
    "payouts": null,
    "fastFunds": null,
    "paymentAccountReference": null
  },
  "destination": null,
  "customer": null,
  "processedOn": null,
  "reference": null,
  "eci": null,
  "schemeId": null,
  "actionsLink": null,
  "captureLink": null,
  "voidLink": null,
  "selfLink": null
}

Estoy usando el SDK de Checkout (versión 3.4.0). Actualmente escribiendo algunas pruebas de integración. Esencialmente, tengo un servidor simulado y he eliminado la respuesta que llama el SDK y cuando mi código llama a un método en ese SDK. Lo anterior es mi respuesta burlada.

Pero me doy cuenta de que mi código no obtiene la respuesta simulada a pesar de que los registros me dicen que mi servidor simulado está devolviendo mi respuesta simulada en función de la solicitud que intentó el SDK. Lo que se devuelve son solo algunos campos completados (como el idpero no el responseSummaryo responseCode) en el objeto.

Después de haberlo depurado aún más, puedo ver dónde se produce la falta de coincidencia:

Este método está en el SDK:

private <T> T deserialize(Transport.Response response, Class<T> responseType) {
    T result = serializer.fromJson(response.getBody(), responseType);
    //a few small business logic here but nothing special
    return result;
}

Cuando depuro, puedo ver que el responseargumento contiene mi respuesta simulada, que es buena y el responseTypeargumento es la clase correcta que estoy esperando. Pero después de la serialización, la resultvariable no contiene los mismos campos que mi respuesta simulada. El serializerobjeto usa Gson para deserializarlo... nada especial (usando el método gson.fromJson())... pero puedo ver que el gson está configurado con algunas configuraciones:

    private static final Gson DEFAULT_GSON = new GsonBuilder()
        .registerTypeAdapter(LocalDate.class, (JsonSerializer<LocalDate>) (LocalDate date, Type typeOfSrc, JsonSerializationContext context) ->
                new JsonPrimitive(date.format(DateTimeFormatter.ISO_LOCAL_DATE)))
        .registerTypeAdapter(Instant.class, (JsonSerializer<Instant>) (Instant date, Type typeOfSrc, JsonSerializationContext context) ->
                new JsonPrimitive(date.toString()))
        .registerTypeAdapter(LocalDate.class, (JsonDeserializer<LocalDate>) (JsonElement json, Type typeOfSrc, JsonDeserializationContext context) ->
                LocalDate.parse(json.getAsString(), DateTimeFormatter.ISO_LOCAL_DATE))
        .registerTypeAdapter(Instant.class, (JsonDeserializer<Instant>) (JsonElement json, Type typeOfSrc, JsonDeserializationContext context) ->
                Instant.parse(json.getAsString()))
        .registerTypeAdapterFactory(RuntimeTypeAdapterFactory.of(ResponseSource.class, "type", true, AlternativePaymentSourceResponse.class)
                .registerSubtype(CardSourceResponse.class, CardSource.TYPE_NAME))
        .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
        .create();

¿Alguien sabe dónde puedo, cómo puedo superar esto o qué podría estar haciendo mal?

Answer

Está creando la instancia de Gson con FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES, sin embargo, los nombres de propiedad en sus datos JSON son mayúsculas y minúsculas. Esta podría ser la razón por la cual la deserialización de propiedades como responseSummaryno funciona porque Gson está esperando response_summary(a menos que estos campos estén anotados con @SerializedName).