Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Nesting multiple levels of Jackson WRAPPER_OBJECTs

By no means am I a Jackon/JSON wizard, which is probably evident from the following issue I'm running into:

I have 2 possible data structures I'm receiving. The first one is called amountTransaction:

{
  "amountTransaction": {
    "clientCorrelator":"54321",
    "endUserId":"tel:+16309700001"
  }
}

Which is represented by the following Java object:

@JsonIgnoreProperties(ignoreUnknown = true)
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT)
@JsonTypeName(value = "amountTransaction")
@JsonInclude(JsonInclude.Include.NON_NULL)
public class AmountTransaction {
  private String clientCorrelator;
  private String endUserId;
  ...
}

However the amountTransaction object also appears as child element of the paymentTransactionNotification object:

{
  "paymentTransactionNotification": {
    "amountTransaction": {
      "clientCorrelator": "54321",
      "endUserId": "tel:+16309700001"
    }
  }
}

..which I thought would be represented by:

@JsonIgnoreProperties(ignoreUnknown = true)
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT)
@JsonTypeName(value = "paymentTransactionNotification")
@JsonInclude(JsonInclude.Include.NON_NULL)
public class PaymentTransactionNotification {
  private AmountTransaction amountTransaction;
  ...
}

Parsing the JSON with the amountTransaction object alone works fine. It's a pretty straightforward example of a WRAPPER_OBJECT.

However when trying to parse the JSON for the paymentTransactionNotification, I'm getting an exception indicating that it can't properly deal with the amountTransaction as element of the paymentTransactionNotification:

com.fasterxml.jackson.databind.JsonMappingException: Could not resolve type id 'clientCorrelator' into a subtype of [simple type, class com.sf.oneapi.pojos.AmountTransaction]

Any thoughts on how I can properly annotate this so my code can properly deal with both stand alone, as well as encapsulated amountTransaction objects?

like image 612
uncrase Avatar asked Nov 20 '14 10:11

uncrase


People also ask

How does Jackson read nested JSON?

A JsonNode is Jackson's tree model for JSON and it can read JSON into a JsonNode instance and write a JsonNode out to JSON. To read JSON into a JsonNode with Jackson by creating ObjectMapper instance and call the readValue() method. We can access a field, array or nested object using the get() method of JsonNode class.

What is the use of @JsonRootName?

@JsonRootName allows to have a root node specified over the JSON. We need to enable wrap root value as well.

What is @JsonUnwrapped?

@JsonUnwrapped is used to unwrap values of objects during serialization or de-serialization.


1 Answers

By default wrapping root node in Jackson is disabled. You can wrap inner objects but if you want to wrap root node you need to enable jackson feature for it (https://jira.codehaus.org/browse/JACKSON-747):

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.enable(SerializationConfig.Feature.WRAP_ROOT_VALUE);
objectMapper.enable(DeserializationConfig.Feature.UNWRAP_ROOT_VALUE);

When you enabled these features you already said Jackson to wrap the root element and you don't need @JsonTypeInfo and @JsonTypeName anymore. You can simple delete them. But now you need to customize the root node name and you can use @JsonRootName for it. Your classes should look like this:

@JsonIgnoreProperties(ignoreUnknown = true)
@JsonRootName("amountTransaction")
@JsonInclude(JsonInclude.Include.NON_NULL)
public class AmountTransaction {
    private String clientCorrelator;
    private String endUserId;
...............
}

And

@JsonIgnoreProperties(ignoreUnknown = true)
@JsonRootName("paymentTransactionNotification")
@JsonInclude(JsonInclude.Include.NON_NULL)
public class PaymentTransactionNotification {
  private AmountTransaction amountTransaction;
.............
}

I've tried and Jackson converted both JSON requests as expected.

like image 118
Ilya Ovesnov Avatar answered Oct 03 '22 06:10

Ilya Ovesnov