I have the following JSON and I would like to map this to an object.
{
"response": {
"original": {
"status": {
"code": "SUCCESS"
},
"organisationNode": [
{
"organisationId": {
"identifier": "2005286047",
"identifierType": "BECBE"
},
"organisationLevel": "Subdivision",
"organisationCode": "ENT_CBE",
"organisationParentNode": {
"organisationId": {
"identifier": "0878016185",
"identifierType": "BEEUN"
},
"organisationLevel": "Entity",
"organisationCode": "ENT_CBE"
}
}
]
}
}
}
And I want my Java Object to look something like this:
public class Structure {
private String status; //SUCCESS
private List<OrganisationNode> organisationNodes;
public class OrganisationNode {
private String organisationId; //2005286047
private String organisationLevel; //Subdivision
private List<OrganisationNode> organisationNodes;
}
}
Is there some kind of Jackson annotation to see for example:
@SomeAnnotation("response.original.status.code")
private String status;
I'm calling the JSON service (which supplies me with the JSON response above) with restTemplate like this:
ResponseEntity<Structure> response = restTemplate.postForEntity(endpoint, requestObject, Structure.class);
There is no Jackson annotation that maps an object field to a Json node in the tree but it is not hard to implement. Here are 3 thins that needs to be done:
Here is the complete example:
public class JacksonContextualSerializer {
@Retention(RetentionPolicy.RUNTIME)
public static @interface SomeAnnotation {
String value();
}
public static final String JSON = "{\n" +
" \"response\": {\n" +
" \"original\": {\n" +
" \"status\": {\n" +
" \"code\": \"SUCCESS\"\n" +
" }\n" +
" }\n" +
" }\n" +
"}";
public static class PathAwareSerializer extends JsonDeserializer<String>
implements ContextualDeserializer {
private String path;
@Override
public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
BeanProperty property)
throws JsonMappingException {
// when the serializer implements the ContextualDeserializer, then we have
// the access to the element's annotation value
path = property.getMember().getAnnotation(SomeAnnotation.class).value();
return this;
}
@Override
public String deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
// read JSON as tree
JsonNode node = jp.readValueAs(JsonNode.class);
// find the last node starting from the second path element, since the first
// is covered by the property name (see the introspector)
String[] pathArray = path.split("\\.");
for (int i = 1; i < pathArray.length; i++) {
node = node.get(pathArray[i]);
}
return node.asText();
}
}
public static class Bean {
private final String status;
@JsonCreator
public Bean(@SomeAnnotation("response.original.status.code") String status) {
this.status = status;
}
@Override
public String toString() {
return "Bean{" +
"status='" + status + '\'' +
'}';
}
}
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
// register an introspector which will inject jackson annotations to elements that are
// marked by the custom annotation.
mapper.setAnnotationIntrospector(new JacksonAnnotationIntrospector() {
@Override
public PropertyName findNameForDeserialization(Annotated a) {
if (a.hasAnnotation(SomeAnnotation.class)) {
// if annotation is present then this is a property which name is the first
// element in the path
String path = a.getAnnotation(SomeAnnotation.class).value();
return new PropertyName(path.split("\\.")[0]);
}
return super.findNameForDeserialization(a);
}
@Override
public Class<? extends JsonDeserializer<?>> findDeserializer(Annotated a) {
// if the annotation is present, then the property is deserialized using
// the custom serializer
if (a.hasAnnotation(SomeAnnotation.class)) {
return PathAwareSerializer.class;
}
return super.findDeserializer(a);
}
});
System.out.println(mapper.readValue(JSON, Bean.class));
}
}
Output:
Bean{status='SUCCESS'}
Spring Documentation says that if you have this dependency in your pom.xml and the tag <mvc:annotation-driven>
in your spring context, Spring MVC automatically registers a JSON converter for your REST template
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
<version>1.9.3</version>
</dependency>
There are a couple of inconsistencies in your JSON string and Java Object. Eg Status
should also be a type with a field code rather than a String
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.