Jackson @JsonSubTypes - Polymorphic deserialization with generics

605 Views Asked by At

I'm trying to deserialize this json body that I don't have any control over. Because the API I'm calling could provide different "data" (arrays of objects) depending on the "method" value, I thought of polymorphism and using @JsonSubTypes. However the current set up gives me an error. I'm already using generics for another case which where "data" is an object and that works fine. But I'm not able to solve this with arrays of objects.

com.fasterxml.jackson.databind.exc.MismatchedInputException: Unexpected token (START_OBJECT), expected START_ARRAY: need JSON Array to contain As.WRAPPER_ARRAY type information for class demo.common.dto.response.data.AccountLedgerResponse

Not sure what it is referring to since "data" json property starts with "[".

JSON

{
    "version": "1.1",
    "result": {
        "signature": "lCteM8iCg++7uyF...TYoY/mc7eUQ6FWNPg==",
        "method": "AccountLedger",
        "data": [{
            "userid": "3839426635",
            "datestamp": "2014-01-30 13:28:45.652299+01",
            "orderid": "3209647863",
            "accountname": "SUSPENSE_ACCOUNT_CLIENT_FUNDS_SWEDEN_ESSE",
            "messageid": "133921",
            "transactiontype": "User deposit of client funds to CLIENT_FUNDS_SWEDEN_ESSE",
            "currency": "EUR",
            "amount": "5.00000000000000000000",
            "gluepayid": "3209647863"
        }, {
            "accountname": "TRANSACTION_FEE_BANK_DEPOSIT",
            "orderid": "3209647863",
            "userid": "3839426635",
            "datestamp": "2014-01-30 13:28:45.652299+01",
            "messageid": "133921",
            "transactiontype": "User deposit of client funds to CLIENT_FUNDS_SWEDEN_ESSE",
            "currency": "SEK",
            "amount": "-3.01",
            "gluepayid": "3209647863"
        }],
        "uuid": "9e4345db-6093-bb35-07d3-e335f1e28793"
    }
}

The expected object:

public record ResultList<T extends ResponseData>(

        @JsonProperty("signature")
        String signature,

        @JsonProperty("uuid")
        UUID uuid,

        @JsonProperty("method")
        Method method,

        @JsonProperty("data")
        @JsonTypeInfo(
                use = JsonTypeInfo.Id.NAME,
                include = JsonTypeInfo.As.EXTERNAL_PROPERTY,
                property = "method")
        @JsonSubTypes({
                @JsonSubTypes.Type(value = AccountLedgerResponse.class, name = "AccountLedger")
        })
        List<T> data) {

    @Builder
    public ResultList {

    }
}
1

There are 1 best solutions below

3
On BEST ANSWER

The List type can't be identified.

Your TypeInfo for AccountLedger should identify a class that contains an array of AccountLedger.

You have to have a class that contains the list, something like:

AccountLedgerList {
    List<AccountLedger> data;
}

and then your method identifies the List object type:

@JsonSubTypes({
    @JsonSubTypes.Type(value = AccountLedgerList.class, name = "AccountLedger")
})