Jackson xml and json root element
The JSON and XML structures are not equivalent. In XML you want a list of RestObject
and in JSON you want a list whose elements wrap instances of RestObject
in another object. This isn't something you can get with a simple Jackson annotation, you would need a custom serializer only for JSON serialization. First of all, getting the desired XML format is straightforward:
class RestObject implements Serializable {
private LocalDateTime timestamp;
private String title;
private String fullText;
private Long id;
private Double value;
}
@JsonRootName("restObjectList")
class RestObjectList {
@JacksonXmlProperty(localName = "restObject")
@JacksonXmlElementWrapper(useWrapping = false)
private List<RestObject> restObjectList;
}
If you absolutely want to wrap each element in the array in json you'll need a custom serializer e.g.
class RestObjectSerializer extends JsonSerializer<RestObject> {
@Override
public void serialize(RestObject value, JsonGenerator gen, SerializerProvider serializers) throws
IOException {
gen.writeStartObject();
gen.writeObjectFieldStart("restObject");
gen.writeObjectField("timeStamp", value.getTimestamp());
gen.writeStringField("title", value.getTitle());
// other fields
gen.writeEndObject();
gen.writeEndObject();
}
}
And register only with the ObjectMapper
that serializes JSON so it doesn't interfere with serialization to XML:
ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule("MyModule");
module.addSerializer(RestObject.class, new RestObjectSerializer());
mapper.registerModule(module);
Yan Khonski
I have experience building global products used from all over the world. I build simple solutions to complex problems. https://github.com/yan-khonski-it https://www.linkedin.com/in/yan-khonski/ https://leetcode.com/yan-khonski-it/
Updated on June 17, 2022Comments
-
Yan Khonski almost 2 years
I have a service which returns objects in JSON and XML format.
http://localhost:8091/apiN/xml/2
XML Result
<restObjectList> <restObjectList> <restObjectList> <timestamp>2017-06-19 17:01:01</timestamp> <title>Rest object</title> <fullText>This is the full text. ID: 1</fullText> <id>1</id> <value>0.1412789210135622</value> </restObjectList> <restObjectList> <timestamp>2017-06-19 17:01:01</timestamp> <title>Rest object</title> <fullText>This is the full text. ID: 2</fullText> <id>2</id> <value>0.9886539664938628</value> </restObjectList> </restObjectList> </restObjectList>
http://localhost:8091/apiN/2
JSON result
{ "restObjectList": [ { "timestamp": "2017-06-19 17:01:01", "title": "Rest object", "fullText": "This is the full text. ID: 1", "id": 1, "value": 0.1412789210135622 }, { "timestamp": "2017-06-19 17:01:01", "title": "Rest object", "fullText": "This is the full text. ID: 2", "id": 2, "value": 0.9886539664938628 } ] }
Result I'd like to receive
xml
<restObjectList> <restObject> <timestamp>2017-06-19 17:01:01</timestamp> <title>Rest object</title> <fullText>This is the full text. ID: 1</fullText> <id>1</id> <value>0.1412789210135622</value> </restObject> <restObject> <timestamp>2017-06-19 17:01:01</timestamp> <title>Rest object</title> <fullText>This is the full text. ID: 2</fullText> <id>2</id> <value>0.9886539664938628</value> </restObject> </restObjectList>
json
{ "restObjectList": [{ "restObject": { "timestamp": "2017-06-19 17:01:01", "title": "Rest object", "fullText": "This is the full text. ID: 1", "id": 1, "value": 0.1412789210135622 } }, { "restObject": { "timestamp": "2017-06-19 17:01:01", "title": "Rest object", "fullText": "This is the full text. ID: 2", "id": 2, "value": 0.9886539664938628 } }] }
How do I wrap
restObject
for JSON and XML and fix XML data forrestObjectList
because this tag is repeated at different levels.My code
RestObject
@JsonRootName(value = "restObject") @XmlRootElement(name = "restObject") public class RestObject implements Serializable { private LocalDateTime timestamp; private String title; private String fullText; private Long id; private Double value; //Getters, setters }
RestObjectList
@JsonRootName(value = "restObjectList") @XmlSeeAlso({RestObject.class}) public class RestObjectList { private List<RestObject> restObjectList; //Getter and setter }
JacksonConfig
@Configuration public class JacksonConfig { @Bean public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) { ObjectMapper objectMapper = builder.createXmlMapper(true).build(); objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);//Use custom date-time format. objectMapper.configure(SerializationFeature.WRAP_ROOT_VALUE, false); objectMapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, false); return objectMapper; } @Bean public ObjectMapper objectMapper() { ObjectMapper objectMapper = new ObjectMapper(); objectMapper.enable(SerializationFeature.WRAP_ROOT_VALUE); objectMapper.enable(DeserializationFeature.UNWRAP_ROOT_VALUE); return objectMapper; } }