sssilver
sssilver

Reputation: 2859

Wrong POST body JSON serialization when using postForEntity in Spring

I'm trying to send an instance of the object EGiftCreationRequest as JSON via POST body in Spring:

    final BigDecimal amount = new BigDecimal(100.00);
    final String configurationId = "test_configuration_id";
    final String referenceNumber = "12345";

    EGiftCreationRequest giftCreationRequest = new EGiftCreationRequest() {{
        giftAmount(amount);
        productConfigurationId(configurationId);
        retrievalReferenceNumber(referenceNumber);
    }};

    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);

    HttpEntity<EGiftCreationRequest> httpEntity = new HttpEntity<EGiftCreationRequest>(giftCreationRequest, headers);

    ResponseEntity<EGift> entity = new TestRestTemplate().postForEntity(
            "http://localhost:" + this.port + "/eGiftProcessing/v1/generateEGift",
            httpEntity,
            EGift.class
    );

However, for some reason the object is being serialized into the following String:

{"headerParams":{}}

Obviously this has nothing to do with my EGiftCreationRequest, which is actually:

public class EGiftCreationRequest extends RequestBase<EGiftCreationRequest> {
    private BigDecimal giftAmount;
    private String productConfigurationId;
    private String retrievalReferenceNumber;

    public BigDecimal giftAmount() {
        return this.giftAmount;
    }

    public String productConfigurationId() {
        return this.productConfigurationId;
    }

    public String retrievalReferenceNumber() {
        return this.retrievalReferenceNumber;
    }

    public EGiftCreationRequest giftAmount(final BigDecimal giftAmount) {
        this.giftAmount = giftAmount;
        return this;
    }

    public EGiftCreationRequest productConfigurationId(final String productConfigurationId) {
        this.productConfigurationId = productConfigurationId;
        return this;
    }

    public EGiftCreationRequest retrievalReferenceNumber(final String retrievalReferenceNumber) {
        this.retrievalReferenceNumber = retrievalReferenceNumber;
        return this;
    }
}

What can possibly be going on?

Upvotes: 1

Views: 2246

Answers (1)

sssilver
sssilver

Reputation: 2859

This is caused by a misconfigured Jackson mapper. By default, Jackson is looking for accessors named in JavaBeans fashion (get*(), set*()) to retrieve and set values. Since the model uses a different naming convention (the field names themselves), Jackson fails to serialize the object.

The following mapper configuration makes everything work correctly:

    ObjectMapper mapper = new ObjectMapper();

    mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
    mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

    mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
    mapper.setVisibility(PropertyAccessor.GETTER, JsonAutoDetect.Visibility.NONE);
    mapper.setVisibility(PropertyAccessor.SETTER, JsonAutoDetect.Visibility.NONE);
    mapper.setVisibility(PropertyAccessor.CREATOR, JsonAutoDetect.Visibility.NONE);

    TestRestTemplate testRestTemplate = new TestRestTemplate();
    List<HttpMessageConverter<?>> messageConverters = new ArrayList<HttpMessageConverter<?>>();
    messageConverters.add(new MappingJackson2HttpMessageConverter(mapper));

    testRestTemplate.setMessageConverters(messageConverters);

Upvotes: 3

Related Questions