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

相关文章

SpringBoot3.4配置校验新特性的用法详解

《SpringBoot3.4配置校验新特性的用法详解》SpringBoot3.4对配置校验支持进行了全面升级,这篇文章为大家详细介绍了一下它们的具体使用,文中的示例代码讲解详细,感兴趣的小伙伴可以参考... 目录基本用法示例定义配置类配置 application.yml注入使用嵌套对象与集合元素深度校验开发

SpringBoot UserAgentUtils获取用户浏览器的用法

《SpringBootUserAgentUtils获取用户浏览器的用法》UserAgentUtils是于处理用户代理(User-Agent)字符串的工具类,一般用于解析和处理浏览器、操作系统以及设备... 目录介绍效果图依赖封装客户端工具封装IP工具实体类获取设备信息入库介绍UserAgentUtils

MySQL 中的 JSON 查询案例详解

《MySQL中的JSON查询案例详解》:本文主要介绍MySQL的JSON查询的相关知识,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录mysql 的 jsON 路径格式基本结构路径组件详解特殊语法元素实际示例简单路径复杂路径简写操作符注意MySQL 的 J

Spring Boot中JSON数值溢出问题从报错到优雅解决办法

《SpringBoot中JSON数值溢出问题从报错到优雅解决办法》:本文主要介绍SpringBoot中JSON数值溢出问题从报错到优雅的解决办法,通过修改字段类型为Long、添加全局异常处理和... 目录一、问题背景:为什么我的接口突然报错了?二、为什么会发生这个错误?1. Java 数据类型的“容量”限制

Spring Boot 整合 SSE的高级实践(Server-Sent Events)

《SpringBoot整合SSE的高级实践(Server-SentEvents)》SSE(Server-SentEvents)是一种基于HTTP协议的单向通信机制,允许服务器向浏览器持续发送实... 目录1、简述2、Spring Boot 中的SSE实现2.1 添加依赖2.2 实现后端接口2.3 配置超时时

Java中的@SneakyThrows注解用法详解

《Java中的@SneakyThrows注解用法详解》:本文主要介绍Java中的@SneakyThrows注解用法的相关资料,Lombok的@SneakyThrows注解简化了Java方法中的异常... 目录前言一、@SneakyThrows 简介1.1 什么是 Lombok?二、@SneakyThrows

Spring 请求之传递 JSON 数据的操作方法

《Spring请求之传递JSON数据的操作方法》JSON就是一种数据格式,有自己的格式和语法,使用文本表示一个对象或数组的信息,因此JSON本质是字符串,主要负责在不同的语言中数据传递和交换,这... 目录jsON 概念JSON 语法JSON 的语法JSON 的两种结构JSON 字符串和 Java 对象互转

Python中的getopt模块用法小结

《Python中的getopt模块用法小结》getopt.getopt()函数是Python中用于解析命令行参数的标准库函数,该函数可以从命令行中提取选项和参数,并对它们进行处理,本文详细介绍了Pyt... 目录getopt模块介绍getopt.getopt函数的介绍getopt模块的常用用法getopt模

mysql中的group by高级用法

《mysql中的groupby高级用法》MySQL中的GROUPBY是数据聚合分析的核心功能,主要用于将结果集按指定列分组,并结合聚合函数进行统计计算,下面给大家介绍mysql中的groupby用法... 目录一、基本语法与核心功能二、基础用法示例1. 单列分组统计2. 多列组合分组3. 与WHERE结合使

Java中Scanner的用法示例小结

《Java中Scanner的用法示例小结》有时候我们在编写代码的时候可能会使用输入和输出,那Java也有自己的输入和输出,今天我们来探究一下,对JavaScanner用法相关知识感兴趣的朋友一起看看吧... 目录前言一 输出二 输入Scanner的使用多组输入三 综合练习:猜数字游戏猜数字前言有时候我们在