0

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 {

    }
}
bob
  • 198
  • 1
  • 10

1 Answers1

3

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")
})
Bill Mair
  • 1,073
  • 6
  • 15
  • Thank you for the quick answer. :) But wouldn't also the `AccountLedgerList` also be an object wrapping the list in this case? – bob Mar 08 '23 at 20:17
  • Okay, it seems like it works thanks to you :) But I had to basically make AccountLedgerList implement List in order to make it work. Was that what you were trying to imply? Or are there other ways instead of having to implement List? – bob Mar 08 '23 at 20:44
  • Yes, JsonSubTypes.Type has to identify the class to be used, not the type that is contained in the List. It is just how I like to code it: `DtoType` and `DtoTypeList`. But as you said `DtoTypeList extends List` is functionally the same . – Bill Mair Mar 09 '23 at 05:49