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

相关文章

JavaScript中的高级调试方法全攻略指南

《JavaScript中的高级调试方法全攻略指南》什么是高级JavaScript调试技巧,它比console.log有何优势,如何使用断点调试定位问题,通过本文,我们将深入解答这些问题,带您从理论到实... 目录观点与案例结合观点1观点2观点3观点4观点5高级调试技巧详解实战案例断点调试:定位变量错误性能分

Python中logging模块用法示例总结

《Python中logging模块用法示例总结》在Python中logging模块是一个强大的日志记录工具,它允许用户将程序运行期间产生的日志信息输出到控制台或者写入到文件中,:本文主要介绍Pyt... 目录前言一. 基本使用1. 五种日志等级2.  设置报告等级3. 自定义格式4. C语言风格的格式化方法

MyBatis-plus处理存储json数据过程

《MyBatis-plus处理存储json数据过程》文章介绍MyBatis-Plus3.4.21处理对象与集合的差异:对象可用内置Handler配合autoResultMap,集合需自定义处理器继承F... 目录1、如果是对象2、如果需要转换的是List集合总结对象和集合分两种情况处理,目前我用的MP的版本

SpringBoot 获取请求参数的常用注解及用法

《SpringBoot获取请求参数的常用注解及用法》SpringBoot通过@RequestParam、@PathVariable等注解支持从HTTP请求中获取参数,涵盖查询、路径、请求体、头、C... 目录SpringBoot 提供了多种注解来方便地从 HTTP 请求中获取参数以下是主要的注解及其用法:1

C#下Newtonsoft.Json的具体使用

《C#下Newtonsoft.Json的具体使用》Newtonsoft.Json是一个非常流行的C#JSON序列化和反序列化库,它可以方便地将C#对象转换为JSON格式,或者将JSON数据解析为C#对... 目录安装 Newtonsoft.json基本用法1. 序列化 C# 对象为 JSON2. 反序列化

Python中Json和其他类型相互转换的实现示例

《Python中Json和其他类型相互转换的实现示例》本文介绍了在Python中使用json模块实现json数据与dict、object之间的高效转换,包括loads(),load(),dumps()... 项目中经常会用到json格式转为object对象、dict字典格式等。在此做个记录,方便后续用到该方

GSON框架下将百度天气JSON数据转JavaBean

《GSON框架下将百度天气JSON数据转JavaBean》这篇文章主要为大家详细介绍了如何在GSON框架下实现将百度天气JSON数据转JavaBean,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下... 目录前言一、百度天气jsON1、请求参数2、返回参数3、属性映射二、GSON属性映射实战1、类对象映

从基础到高级详解Python数值格式化输出的完全指南

《从基础到高级详解Python数值格式化输出的完全指南》在数据分析、金融计算和科学报告领域,数值格式化是提升可读性和专业性的关键技术,本文将深入解析Python中数值格式化输出的相关方法,感兴趣的小伙... 目录引言:数值格式化的核心价值一、基础格式化方法1.1 三种核心格式化方式对比1.2 基础格式化示例

Java中HashMap的用法详细介绍

《Java中HashMap的用法详细介绍》JavaHashMap是一种高效的数据结构,用于存储键值对,它是基于哈希表实现的,提供快速的插入、删除和查找操作,:本文主要介绍Java中HashMap... 目录一.HashMap1.基本概念2.底层数据结构:3.HashCode和equals方法为什么重写Has

Android协程高级用法大全

《Android协程高级用法大全》这篇文章给大家介绍Android协程高级用法大全,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友跟随小编一起学习吧... 目录1️⃣ 协程作用域(CoroutineScope)与生命周期绑定Activity/Fragment 中手