Search code examples
sap-cloud-sdk

Override JsonDeserializer Behavior


The generator has created a field of type OffsetDateTime:

@Nullable
@ElementName("DocDate")
private OffsetDateTime docDate;

But the server actually returns dates in the format: YYYY-mm-dd i.e. 2021-03-07

When using the generated code I get the following warnings:

WARN - Not deserializable: 2021-03-07

What is the correct way to override the deserialization of these fields? Or have these fields deserialize correctly?


Solution

  • An OffsetDateTime should have both a date and a time. The data your service responds with is lacking the time part. As per the OData V4 ABNF, this is not allowed (assuming your service is a V4 service):

    dateTimeOffsetValue = year "-" month "-" day "T" hour ":" minute [ ":" second [ "." fractionalSeconds ] ] ( "Z" / SIGN hour ":" minute )
    

    One way to solve this is to change the property type. You could either:

    1. Change it to Edm.Date in the specification
    2. Or change it to LocalDate in the generated code.

    Of course this only makes sense if the service will always respond with a date.


    Edit: If you really need to register a custom type adapter (e.g. because the service violates the JSON format) you could override the GsonVdmAdapterFactory:

    public <T> TypeAdapter<T> create( @Nonnull final Gson gson, @Nonnull final TypeToken<T> type )
    {
        if( LocalDate.class.isAssignableFrom(rawType) ) {
            return (TypeAdapter<T>) new CustomLocalDateTypeAdapter();
        } else {
            return super.create(gson, type);
        }
    }
    

    However, this also requires changing the generated code, because there is currently no convenience to pass a custom type adapter as parameter. Change @JsonAdapter(com.sap.cloud.sdk.datamodel.odatav4.adapter.GsonVdmAdapterFactory.class) to reference your custom factory.

    Still, I'd recommend using one of the above workarounds until the service is fixed.