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

相关文章

Python中列表的高级索引技巧分享

《Python中列表的高级索引技巧分享》列表是Python中最常用的数据结构之一,它允许你存储多个元素,并且可以通过索引来访问这些元素,本文将带你深入了解Python列表的高级索引技巧,希望对... 目录1.基本索引2.切片3.负数索引切片4.步长5.多维列表6.列表解析7.切片赋值8.删除元素9.反转列表

Springboot中Jackson用法详解

《Springboot中Jackson用法详解》Springboot自带默认json解析Jackson,可以在不引入其他json解析包情况下,解析json字段,下面我们就来聊聊Springboot中J... 目录前言Jackson用法将对象解析为json字符串将json解析为对象将json文件转换为json

Java解析JSON的六种方案

《Java解析JSON的六种方案》这篇文章介绍了6种JSON解析方案,包括Jackson、Gson、FastJSON、JsonPath、、手动解析,分别阐述了它们的功能特点、代码示例、高级功能、优缺点... 目录前言1. 使用 Jackson:业界标配功能特点代码示例高级功能优缺点2. 使用 Gson:轻量

正则表达式高级应用与性能优化记录

《正则表达式高级应用与性能优化记录》本文介绍了正则表达式的高级应用和性能优化技巧,包括文本拆分、合并、XML/HTML解析、数据分析、以及性能优化方法,通过这些技巧,可以更高效地利用正则表达式进行复杂... 目录第6章:正则表达式的高级应用6.1 模式匹配与文本处理6.1.1 文本拆分6.1.2 文本合并6

python中json.dumps和json.dump区别

《python中json.dumps和json.dump区别》json.dumps将Python对象序列化为JSON字符串,json.dump直接将Python对象序列化写入文件,本文就来介绍一下两个... 目录1、json.dumps和json.dump的区别2、使用 json.dumps() 然后写入文

Java中JSON字符串反序列化(动态泛型)

《Java中JSON字符串反序列化(动态泛型)》文章讨论了在定时任务中使用反射调用目标对象时处理动态参数的问题,通过将方法参数存储为JSON字符串并进行反序列化,可以实现动态调用,然而,这种方式容易导... 需求:定时任务扫描,反射调用目标对象,但是,方法的传参不是固定的。方案一:将方法参数存成jsON字

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

bytes.split的用法和注意事项

当然,我很乐意详细介绍 bytes.Split 的用法和注意事项。这个函数是 Go 标准库中 bytes 包的一个重要组成部分,用于分割字节切片。 基本用法 bytes.Split 的函数签名如下: func Split(s, sep []byte) [][]byte s 是要分割的字节切片sep 是用作分隔符的字节切片返回值是一个二维字节切片,包含分割后的结果 基本使用示例: pa

UVM:callback机制的意义和用法

1. 作用         Callback机制在UVM验证平台,最大用处就是为了提高验证平台的可重用性。在不创建复杂的OOP层次结构前提下,针对组件中的某些行为,在其之前后之后,内置一些函数,增加或者修改UVM组件的操作,增加新的功能,从而实现一个环境多个用例。此外还可以通过Callback机制构建异常的测试用例。 2. 使用步骤         (1)在UVM组件中内嵌callback函

Java基础回顾系列-第七天-高级编程之IO

Java基础回顾系列-第七天-高级编程之IO 文件操作字节流与字符流OutputStream字节输出流FileOutputStream InputStream字节输入流FileInputStream Writer字符输出流FileWriter Reader字符输入流字节流与字符流的区别转换流InputStreamReaderOutputStreamWriter 文件复制 字符编码内存操作流(