JSON Views 高级用法

2024-03-08 21:18
文章标签 json 用法 高级 views

本文主要是介绍JSON Views 高级用法,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

原帖地址:

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 for Jackson’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:

@RestController
public class MessageController {@Autowiredprivate 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 to false. That means that when enabling a JSON View, non annotated fields or properties like body 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 {@Autowiredprivate 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 or MappingJackson2JsonView 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:

@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 MappingJackson2JsonView with 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 using ObjectMapper 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 create ObjectMapper and XmlMapper instances based on the same configuration.

Both Jackson2ObjectMapperBuilder and Jackson2ObjectMapperFactoryBean define a better Jackson default configuration. For example, the DeserializationFeature.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 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 to customize the Jackson ObjectMapper.

You can for example enable/disable Jackson features easily by adding properties like spring.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 MVC HttpMessageConverters by declaring a Jackson2ObjectMapperBuilder @Bean:

@Bean
public 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 all Module @Bean. For example to register jackson-module-parameter-names:

@Bean
public 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 JSON HttpMessageConverters as shown bellow:

@Configuration
@EnableWebMvc
public class WebConfiguration extends WebMvcConfigurerAdapter {@Overridepublic 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:

  • jackson-datatype-jdk7: Java 7 types like java.nio.file.Path (as of 4.2.1 release)
  • jackson-datatype-joda: Joda-Time types
  • jackson-datatype-jsr310: Java 8 Date & Time API data types
  • jackson-datatype-jdk8: other Java 8 types like Optional (as of 4.2.0 release)

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

  • jackson-module-parameter-names: adds support for accessing parameter names (feature added in Java 8)
  • jackson-datatype-money: javax.money types (unofficial module)
  • jackson-datatype-hibernate: Hibernate specific types and properties (including lazy-loading aspects)

Advanced features

As of Spring Framework 4.1.3, thanks to the addition of a Spring context aware HandlerInstantiator (see SPR-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 full Entity retrieved from the database.


这篇关于JSON Views 高级用法的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/788428

相关文章

MySQL 中的 CAST 函数详解及常见用法

《MySQL中的CAST函数详解及常见用法》CAST函数是MySQL中用于数据类型转换的重要函数,它允许你将一个值从一种数据类型转换为另一种数据类型,本文给大家介绍MySQL中的CAST... 目录mysql 中的 CAST 函数详解一、基本语法二、支持的数据类型三、常见用法示例1. 字符串转数字2. 数字

Python中你不知道的gzip高级用法分享

《Python中你不知道的gzip高级用法分享》在当今大数据时代,数据存储和传输成本已成为每个开发者必须考虑的问题,Python内置的gzip模块提供了一种简单高效的解决方案,下面小编就来和大家详细讲... 目录前言:为什么数据压缩如此重要1. gzip 模块基础介绍2. 基本压缩与解压缩操作2.1 压缩文

解读GC日志中的各项指标用法

《解读GC日志中的各项指标用法》:本文主要介绍GC日志中的各项指标用法,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、基础 GC 日志格式(以 G1 为例)1. Minor GC 日志2. Full GC 日志二、关键指标解析1. GC 类型与触发原因2. 堆

MySQL查询JSON数组字段包含特定字符串的方法

《MySQL查询JSON数组字段包含特定字符串的方法》在MySQL数据库中,当某个字段存储的是JSON数组,需要查询数组中包含特定字符串的记录时传统的LIKE语句无法直接使用,下面小编就为大家介绍两种... 目录问题背景解决方案对比1. 精确匹配方案(推荐)2. 模糊匹配方案参数化查询示例使用场景建议性能优

MySQL数据库中ENUM的用法是什么详解

《MySQL数据库中ENUM的用法是什么详解》ENUM是一个字符串对象,用于指定一组预定义的值,并可在创建表时使用,下面:本文主要介绍MySQL数据库中ENUM的用法是什么的相关资料,文中通过代码... 目录mysql 中 ENUM 的用法一、ENUM 的定义与语法二、ENUM 的特点三、ENUM 的用法1

JavaSE正则表达式用法总结大全

《JavaSE正则表达式用法总结大全》正则表达式就是由一些特定的字符组成,代表的是一个规则,:本文主要介绍JavaSE正则表达式用法的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录常用的正则表达式匹配符正则表China编程达式常用的类Pattern类Matcher类PatternSynta

MySQL之InnoDB存储引擎中的索引用法及说明

《MySQL之InnoDB存储引擎中的索引用法及说明》:本文主要介绍MySQL之InnoDB存储引擎中的索引用法及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录1、背景2、准备3、正篇【1】存储用户记录的数据页【2】存储目录项记录的数据页【3】聚簇索引【4】二

mysql中的数据目录用法及说明

《mysql中的数据目录用法及说明》:本文主要介绍mysql中的数据目录用法及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、版本3、数据目录4、总结1、背景安装mysql之后,在安装目录下会有一个data目录,我们创建的数据库、创建的表、插入的

深度解析Python装饰器常见用法与进阶技巧

《深度解析Python装饰器常见用法与进阶技巧》Python装饰器(Decorator)是提升代码可读性与复用性的强大工具,本文将深入解析Python装饰器的原理,常见用法,进阶技巧与最佳实践,希望可... 目录装饰器的基本原理函数装饰器的常见用法带参数的装饰器类装饰器与方法装饰器装饰器的嵌套与组合进阶技巧

Mysql中isnull,ifnull,nullif的用法及语义详解

《Mysql中isnull,ifnull,nullif的用法及语义详解》MySQL中ISNULL判断表达式是否为NULL,IFNULL替换NULL值为指定值,NULLIF在表达式相等时返回NULL,用... 目录mysql中isnull,ifnull,nullif的用法1. ISNULL(expr) → 判