Search code examples
javaspringxmlhttprequest

Jackson doesn't unmarshall xml correctly in Spring


I'd like to write a rest service that accepts and produces XML or JSON based on the information from headers. To do so, I followed one of tutorials. The problem is that when I try to read fields of dto in Spring controller, they are all set to null.

For test purposes, I send in body a DTO and in controller I return it concatenating string Changed to two of its fields.

In body I send:

<?xml version="1.0" encoding="UTF-8"?>
<name>name</name>
<description>description</description>

However, I receive:

<Dto name="null Changed" description="null Changed"/>

I send request by Postman:

enter image description here

Here's my configuration:

Controller

@RestController
public class Controller {

    @RequestMapping(value = "/endpoint", method = RequestMethod.POST,
            consumes = {APPLICATION_JSON_VALUE, APPLICATION_XML_VALUE},
            produces = {APPLICATION_JSON_VALUE, APPLICATION_XML_VALUE})

    public Dto getAndReturnEntity(@RequestBody Dto dto) {

    dto.setName(dto.getName() + " Changed");
    dto.setDescription(dto.getDescription() + " Changed");
    return dto;
    }
}

DTO

@JacksonXmlRootElement
public class Dto {

@JacksonXmlProperty(isAttribute = true) // I also tried without it
private String name;

@JacksonXmlProperty(isAttribute = true)
private String description;

// getters and setters ommited for brevity
}

Configuration for Spring

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {

    @Override
    public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
        configurer.favorPathExtension(true).
                favorParameter(false).
                parameterName("mediaType").
                ignoreAcceptHeader(false).
                useJaf(false).
                defaultContentType(MediaType.APPLICATION_JSON).
                mediaType("xml", MediaType.APPLICATION_XML).
                mediaType("json", MediaType.APPLICATION_JSON);
    }
}

Relevant part of pom.xml

   <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
    </dependency>

    <dependency>
        <groupId>com.fasterxml.jackson.dataformat</groupId>
        <artifactId>jackson-dataformat-xml</artifactId>
    </dependency>

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
    </dependency>

Solution

  • The input XML should be like this:

    <Dto>
      <name>abcd</name>
      <description>desc</description>
    </Dto>
    

    In case you want the tag names be different than you can use either custom object mapper or add @JsonProperty.