DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
View Events Video Library
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

UK-US Data Bridge: Join TechnologyAdvice and OneTrust as they discuss the UK extension to the EU-US Data Privacy Framework (DPF).

Migrate, Modernize and Build Java Web Apps on Azure: This live workshop will cover methods to enhance Java application development workflow.

Kubernetes in the Enterprise: The latest expert insights on scaling, serverless, Kubernetes-powered AI, cluster security, FinOps, and more.

A Guide to Continuous Integration and Deployment: Learn the fundamentals and understand the use of CI/CD in your apps.

Related

  • Secure Spring Boot Application With Keycloak
  • Spring Config Integration With a PCF Application: A Step-by-Step Guide
  • Integration Between Java and Slack With Webhooks
  • Spring Boot Centralized Logging with Graylog

Trending

  • Kafka Event Streaming AI and Automation
  • Unlocking Clean Code: 20 Architectural Tips for Every Developer
  • The ABCs of Unity's Coroutines: From Basics to Implementation
  • GitHub Shared Responsibility Model and Source Code Protection
  1. DZone
  2. Coding
  3. Frameworks
  4. Latest Jackson Integration Improvements in Spring

Latest Jackson Integration Improvements in Spring

Pieter Humphrey user avatar by
Pieter Humphrey
DZone Core CORE ·
Dec. 09, 14 · Interview
Like (1)
Save
Tweet
Share
31.2K Views

Join the DZone community and get the full member experience.

Join For Free
Originally written by Sébastien Deluze  on the SpringSource blog

Spring Jackson support has been improved lately to be more flexible and powerful. This blog post gives you an update about the most useful Jackson related features available in Spring Framework 4.x and Spring Boot. All the code samples are coming from this spring-jackson-demo sample application, feel free to have a look at the code.

JSON Views

It can sometimes be useful to filter contextually objects serialized to the HTTP response body. In order to provide such capabilities, Spring MVC now has builtin support for Jackson’s Serialization Views.

The following example illustrates how to use @JsonView to filter fields depending on the context of serialization - e.g. getting a "summary" view when dealing with collections, and getting a full representation when dealing with a single resource:

public class View {
    interface Summary {}
}

public class User {

    @JsonView(View.Summary.class)
    private Long id;

    @JsonView(View.Summary.class)
    private String firstname;

    @JsonView(View.Summary.class)
    private String lastname;

    private String email;
    private String address;
    private String postalCode;
    private String city;
    private String country;
}

public class Message {

    @JsonView(View.Summary.class)
    private Long id;

    @JsonView(View.Summary.class)
    private LocalDate created;

    @JsonView(View.Summary.class)
    private String title;

    @JsonView(View.Summary.class)
    private User author;

    private List<User> recipients;

    private String body;
}

Thanks to Spring MVC @JsonView support, it is possible to choose, on a per handler method basis, which field should be serialized:

@RestController
public class MessageController {

    @Autowired
    private MessageService messageService;

    @JsonView(View.Summary.class)
    @RequestMapping("/")
    public List<Message> getAllMessages() {
        return messageService.getAll();
    }

    @RequestMapping("/{id}")
    public Message getMessage(@PathVariable Long id) {
        return messageService.get(id);
    }
}

In this example, if all messages are retrieved, only the most important fields are serialized thanks to the getAllMessages() method annotated with@JsonView(View.Summary.class):

[ {
  "id" : 1,
  "created" : "2014-11-14",
  "title" : "Info",
  "author" : {
    "id" : 1,
    "firstname" : "Brian",
    "lastname" : "Clozel"
  }
}, {
  "id" : 2,
  "created" : "2014-11-14",
  "title" : "Warning",
  "author" : {
    "id" : 2,
    "firstname" : "Stéphane",
    "lastname" : "Nicoll"
  }
}, {
  "id" : 3,
  "created" : "2014-11-14",
  "title" : "Alert",
  "author" : {
    "id" : 3,
    "firstname" : "Rossen",
    "lastname" : "Stoyanchev"
  }
} ]

In Spring MVC default configuration, MapperFeature.DEFAULT_VIEW_INCLUSION is set tofalse. That means that when enabling a JSON View, non annotated fields or properties likebody or recipients are not serialized.

When a specific Message is retrieved using the getMessage() handler method (no JSON View specified), all fields are serialized as expected:

{
  "id" : 1,
  "created" : "2014-11-14",
  "title" : "Info",
  "body" : "This is an information message",
  "author" : {
    "id" : 1,
    "firstname" : "Brian",
    "lastname" : "Clozel",
    "email" : "bclozel@pivotal.io",
    "address" : "1 Jaures street",
    "postalCode" : "69003",
    "city" : "Lyon",
    "country" : "France"
  },
  "recipients" : [ {
    "id" : 2,
    "firstname" : "Stéphane",
    "lastname" : "Nicoll",
    "email" : "snicoll@pivotal.io",
    "address" : "42 Obama street",
    "postalCode" : "1000",
    "city" : "Brussel",
    "country" : "Belgium"
  }, {
    "id" : 3,
    "firstname" : "Rossen",
    "lastname" : "Stoyanchev",
    "email" : "rstoyanchev@pivotal.io",
    "address" : "3 Warren street",
    "postalCode" : "10011",
    "city" : "New York",
    "country" : "USA"
  } ]
}

Only one class or interface can be specified with the @JsonView annotation, but you can use inheritance to represent JSON View hierarchies (if a field is part of a JSON View, it will be also part of parent view). For example, this handler method will serialize fields annotated with@JsonView(View.Summary.class) and @JsonView(View.SummaryWithRecipients.class):

public class View {
    interface Summary {}
    interface SummaryWithRecipients extends Summary {}
}

public class Message {

    @JsonView(View.Summary.class)
    private Long id;

    @JsonView(View.Summary.class)
    private LocalDate created;

    @JsonView(View.Summary.class)
    private String title;

    @JsonView(View.Summary.class)
    private User author;

    @JsonView(View.SummaryWithRecipients.class)
    private List<User> recipients;

    private String body;
}

@RestController
public class MessageController {

    @Autowired
    private MessageService messageService;

    @JsonView(View.SummaryWithRecipients.class)
    @RequestMapping("/with-recipients")
    public List<Message> getAllMessagesWithRecipients() {
        return messageService.getAll();
    }
}

JSON Views could also be specified when using RestTemplate HTTP client orMappingJackson2JsonView by wrapping the value to serialize in a MappingJacksonValue as shown in this code sample.

JSONP

As described in the reference documentation, you can enable JSONP for @ResponseBody andResponseEntity methods by declaring an @ControllerAdvice bean that extendsAbstractJsonpResponseBodyAdvice as shown below:

@ControllerAdvice
public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice {

    public JsonpAdvice() {
        super("callback");
    }
}

With such @ControllerAdvice bean registered, it will be possible to request the JSON webservice from another domain using a <script /> tag:

<script type="application/javascript"
            src="http://mydomain.com/1.json?jsonp=parseResponse">
</script>

In this example, the received payload would be:

parseResponse({
  "id" : 1,
  "created" : "2014-11-14",
  ...
});

JSONP is also supported and automatically enabled when using MappingJackson2JsonViewwith a request that has a query parameter named jsonp or callback. The JSONP query parameter name(s) could be customized through the jsonpParameterNames property.

XML support

Since 2.0 release, Jackson provides first class support for some other data formats than JSON. Spring Framework and Spring Boot provide builtin support for Jackson based XML serialization/deserialization.

As soon as you include the jackson-dataformat-xml dependency to your project, it is automatically used instead of JAXB2.

Using Jackson XML extension has several advantages over JAXB2:

  • Both Jackson and JAXB annotations are recognized
  • JSON View are supported, allowing you to build easily REST Webservices with the same filtered output for both XML and JSON data formats
  • No need to annotate your class with @XmlRootElement, each class serializable in JSON will serializable in XML

You usually also want to make sure that the XML library in use is Woodstox since:

  • It is faster than Stax implementation provided with the JDK
  • It avoids some known issues like adding unnecessary namespace prefixes
  • Some features like pretty print don't work without it

In order to use it, simply add the latest woodstox-core-asl dependency available to your project.

Customizing the Jackson ObjectMapper

Prior to Spring Framework 4.1.1, Jackson HttpMessageConverters were usingObjectMapper default configuration. In order to provide a better and easily customizable default configuration, a new Jackson2ObjectMapperBuilder has been introduced. It is the JavaConfig equivalent of the well known Jackson2ObjectMapperFactoryBean used in XML configuration.

Jackson2ObjectMapperBuilder provides a nice API to customize various Jackson settings while retaining Spring Framework provided default ones. It also allows to createObjectMapper and XmlMapper instances based on the same configuration.

Both Jackson2ObjectMapperBuilder and Jackson2ObjectMapperFactoryBean define a better Jackson default configuration. For example, theDeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES property set to false, in order to allow deserialization of JSON objects with unmapped properties.

Jackson support for Java 8 Date & Time API data types is automatically registered when Java 8 is used and jackson-datatype-jsr310 is on the classpath. Joda-Time support is registered as well when jackson-datatype-joda is part of your project dependencies.

These classes also allow you to register easily Jackson mixins, modules, serializers or even property naming strategy like PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES if you want to have your userName java property translated to user_name in JSON.

With Spring Boot

As described in the Spring Boot reference documentation, there are various ways tocustomize the Jackson ObjectMapper.

You can for example enable/disable Jackson features easily by adding properties likespring.jackson.serialization.indent_output=true to application.properties.

As an alternative, in the upcoming 1.2 release Spring Boot also allows to customize the Jackson configuration (JSON and XML) used by Spring MVC HttpMessageConverters by declaring a Jackson2ObjectMapperBuilder @Bean:

@Bean
public Jackson2ObjectMapperBuilder jacksonBuilder() {
    Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
    builder.indentOutput(true).dateFormat(new SimpleDateFormat("yyyy-MM-dd"));
    return builder;
}

This is useful if you want to use advanced Jackson configuration not exposed through regular configuration keys.

Without Spring Boot

In a plain Spring Framework application, you can also use Jackson2ObjectMapperBuilder to customize the XML and JSON HttpMessageConverters as shown bellow:

@Configuration
@EnableWebMvc
public class WebConfiguration extends WebMvcConfigurerAdapter {

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
        builder.indentOutput(true).dateFormat(new SimpleDateFormat("yyyy-MM-dd"));
        converters.add(new MappingJackson2HttpMessageConverter(builder.build()));
        converters.add(new MappingJackson2XmlHttpMessageConverter(builder.createXmlMapper(true).build()));
    }
}

More to come

With the upcoming Spring Framework 4.1.3 release, thanks to the addition of a Spring context aware HandlerInstantiator (see SPR-10768 for more details), you will be able to autowire Jackson handlers (serializers, deserializers, type and type id resolvers).

This will allow you to build, for example, a custom deserializer that will replace a field containing only a reference in the JSON payload by the full Entity retrieved from the database.

Spring Framework Jackson (API) Spring Boot JSON XML Integration

Published at DZone with permission of Pieter Humphrey, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Secure Spring Boot Application With Keycloak
  • Spring Config Integration With a PCF Application: A Step-by-Step Guide
  • Integration Between Java and Slack With Webhooks
  • Spring Boot Centralized Logging with Graylog

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends: