Manuel Jordan
Manuel Jordan

Reputation: 16271

Common @Bean configuration for serialization for MappingJackson2HttpMessageConverter and MappingJackson2XmlHttpMessageConverter

For a Spring Web Application working with Jackson for XML and JSON through:

These classes are used for Rest purposes and each one are configured through a @Bean method and both use the following:

@Bean
public Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder(){
    Jackson2Ob jectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
    builder.simpleDateFormat("yyyy-MM-dd");
    return builder;
}

For Date serialization is mandatory use:

@JsonProperty("fecha")
@JsonSerialize(using=JsonDateSerializer.class)
@XmlJavaTypeAdapter(XmlDateAdapter.class)
@JacksonXmlProperty(localName="fecha")
public Date getFecha() {
    return fecha;
}

I want to know if is possible avoid these @JsonSerialize and @XmlJavaTypeAdapter annotations and trust through a central @Bean method that offers a configuration that should be used for both these MappingJackson2HttpMessageConverter and MappingJackson2XmlHttpMessageConverter converters; where the Date 'serialization' should be applied from that configuration. Consider the same about 'formatting' numbers such as BigDecimal and currency too.

Currently with the code shown above I must use @JsonSerialize and @XmlJavaTypeAdapter mandatorily.

Note: for Jackson XML, jackson-dataformat-xml is used instead of JAXB 2 due a limitation about of Generic Collections.

Upvotes: 1

Views: 916

Answers (1)

ritesh.garg
ritesh.garg

Reputation: 3943

Unless I am totally misunderstanding the context here, you can configure jackson Object mapper to use JaxbAnnotationIntrospector as well. With that Jackson will respect the jaxb annotations while marshalling/unmarshalling.

Usually the configuration for that looks something like this:

@Bean
public Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder(){
    Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
    AnnotationIntrospector annotationIntrospector =  AnnotationIntrospector.pair(
            new JaxbAnnotationIntrospector(),

            new JacksonAnnotationIntrospector()
    );
    builder.annotationIntrospector(annotationIntrospector);
    // This is to make jackson respect @XmlElementWrapper annotation and use wrapper name as the property name
    builder.defaultUseWrapper(true);
    return builder;
}

And your entity date field will look like:

@XmlJavaTypeAdapter(XmlDateAdapter.class)
@XmlElement(value = "fetcha") // This is not mandatory to add. If your class is annnotated with @XmlRootElement annotation, by default the field name will be picked up as the name of the element.
public Date getFecha() {
    return fecha;
}

If you want to get rid of @XmlJavaTypeAdapter altogether and just want it to be serialized the way you want in json, you can create a custom json serializer and deserializer classes extending jackson's JsonSerializer and JsonDeserializer.

One such example of a custom serializer from Jackson custom date serializer (I modified this to not rely on a custom annotation and hence to not implement ContextualSerializer)

 public static class CustomDateSerializer extends JsonSerializer<Date>
            {
        private final String format;

        private CustomDateSerializer(final String format) {this.format = format;}

        public CustomDateSerializer() {this.format = null;}

        @Override
        public void serialize(
                final Date value, final JsonGenerator jgen, final SerializerProvider provider)
                throws IOException {
            jgen.writeString(new SimpleDateFormat(format).format(value));
        }

Similarly, you will need to create a custom Deserializer as well if you intend to deserialize Date json element to Date object. Then register them for Date class with Jackson2ObjectMapperBuilder.

builder.serializerByType(Date.class, new CustomDateSerializer());
builder.deserializerByType(Date.class, new CustomDateDeSerializer());

Upvotes: 2

Related Questions