打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
JSON Views 高级用法

2016-04-15 15:22 1548人阅读 评论(0) 收藏 举报
分类:

目录(?)[+]

原帖地址:

http://spring.io/blog/2014/12/02/latest-jackson-integration-improvements-in-spring

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 forJackson’s Serialization Views (as of Spring Framework 4.2, JSON Views are supported on@MessageMapping handler methods as well).

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:

@RestControllerpublic 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 thegetAllMessages() 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;}@RestControllerpublic 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 and ResponseEntity methods by declaring an@ControllerAdvice bean that extends AbstractJsonpResponseBodyAdvice as shown below:

@ControllerAdvicepublic 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 MappingJackson2JsonView with a request that has a query parameter named jsonp or callback. The JSONP query parameter name(s) could be customized through thejsonpParameterNames 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 newJackson2ObjectMapperBuilder has been introduced. It is the JavaConfig equivalent of the well knownJackson2ObjectMapperFactoryBean 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.

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 youruserName 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, Spring Boot also allows to customize the Jackson configuration (JSON and XML) used by Spring MVCHttpMessageConverters by declaring a Jackson2ObjectMapperBuilder@Bean:

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

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

If you just need to register an additional Jackson module, be aware that Spring Boot autodetects allModule @Bean. For example to register jackson-module-parameter-names:

@Beanpublic Module parameterNamesModule() {  return new ParameterNamesModule(JsonCreator.Mode.PROPERTIES);}

Without Spring Boot

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

@Configuration@EnableWebMvcpublic 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()));	}}

Jackson modules

Some well known Jackson modules are automatically registered if they are detected on the classpath:

Some other modules are not registered by default (mainly because they require additional configuration) so you will have to register them explicitly, for example withJackson2ObjectMapperBuilder#modulesToInstall() or by declaring a JacksonModule @Bean if you are using Spring Boot:

Advanced features

As of Spring Framework 4.1.3, thanks to the addition of a Spring context awareHandlerInstantiator (seeSPR-10768 for more details), you are able to autowire Jackson handlers (serializers, deserializers, type and type id resolvers).

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


0
0
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
SpringBoot序列化与反序列化
Spring mvc3 jackson输出null为空字符串、单引号、字段和数字加引号问题
A MappingJacksonJsonView (springframework ) and spring-json view comparison
SpringMVC返回json数据的三种方式
Spring MVC 4.0 RESTFul Web Service JSON Response with @ResponseBody | ProgrammingFree
jackson框架的使用-annotation(注解)、属性的过滤
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服