Search code examples
javaspring-bootspring-jmsjackson2

Configure JSON output in Spring JMS messages


What I would like

In a Spring Boot 1.5.2 project, I'm sending JSON messages to some JMS (ActiveMQ) queues/topics via JmsTemplate#convertAndSend. I use Java 8 with some instances of LocalDate and LocalDateTime. I would like to change the JSON output slightly:

  • pretty-print the JSON; and
  • render dates / timestamps in ISO format.

By default, the JSON ends up all in one line, and dates / timestamps are converted to a fielded format, for example:

"startDate" : { "year" : 2017, "month" : "MARCH", "era" : "CE", "dayOfYear" : 64, "dayOfWeek" : "SUNDAY", "leapYear" : false, "dayOfMonth" : 5, "monthValue" : 3, "chronology" : { "calendarType" : "iso8601", "id" : "ISO" } }

What I've tried

I've added jackson-datatype-jsr310 to the project dependencies and I've also set

spring.jackson.serialization.indent-output=true
spring.jackson.serialization.write_dates_as_timestamps=false

in application.properties. No change in behaviour.

I then tried amending the initialisation of the message converter to include these settings:

@Bean
@Primary
public MessageConverter jacksonJmsMessageConverter() {
    MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
    converter.setTargetType(MessageType.TEXT);
    converter.setTypeIdPropertyName("_type");

    ObjectMapper objectMapper = new ObjectMapper();
    // default settings for MappingJackson2MessageConverter
    objectMapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false);
    objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    // add settings I want
    objectMapper.enable(SerializationFeature.INDENT_OUTPUT);
    objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
    converter.setObjectMapper(objectMapper);

    return converter;
}

But there is still no change in behaviour.

How can I customise the JSON output as described above?


Solution

  • Further configure the object mapper like so:

        JavaTimeModule timeModule = new JavaTimeModule();
        timeModule.addSerializer(LocalDate.class, 
            new LocalDateSerializer(DateTimeFormatter.ISO_LOCAL_DATE));
        timeModule.addSerializer(LocalDateTime.class, 
            new LocalDateTimeSerializer(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
        objectMapper.registerModule(timeModule);
    

    in line with this answer here: https://stackoverflow.com/a/41089874/72625