JSON Views 高级用法
2016-04-15 15:22
549 查看
原帖地址:
http://spring.io/blog/2014/12/02/latest-jackson-integration-improvements-in-spring
Jackson’s Serialization Views (as of Spring Framework 4.2, JSON Views are supported on
The following example illustrates how to use
Thanks to Spring MVC
In this example, if all messages are retrieved, only the most important fields are serialized thanks to the
In Spring MVC default configuration,
When a specific
Only one class or interface can be specified with the
this handler method will serialize fields annotated with
and
JSON Views could also be specified when using
code sample.
reference documentation, you can enable
JSONP for
With such
In this example, the received payload would be:
JSONP is also supported and automatically enabled when using
As soon as you include the
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
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
while retaining Spring Framework provided default ones. It also allows to create
Both
These classes also allow you to register easily Jackson
mixins,
modules,
serializers or even property naming strategy like
customize the Jackson
You can for example enable/disable Jackson features easily by adding properties like
As an alternative, Spring Boot also allows to customize the Jackson configuration (JSON and XML) used by Spring MVC
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
jackson-module-parameter-names:
jackson-datatype-jdk7: Java 7 types like
jackson-datatype-joda: Joda-Time types
jackson-datatype-jsr310: Java 8 Date & Time API data types
jackson-datatype-jdk8: other Java 8 types like
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
jackson-module-parameter-names: adds support for accessing parameter names (feature added in Java 8)
jackson-datatype-money:
jackson-datatype-hibernate: Hibernate specific types and properties (including lazy-loading aspects)
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
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
@MessageMappinghandler methods as well).
The following example illustrates how to use
@JsonViewto 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
@JsonViewsupport, it is possible to choose, on a per handler method basis, which field should be serialized:
@RestController public 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 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_INCLUSIONis set to
false. That means that when enabling a JSON View, non annotated fields or properties like
bodyor
recipientsare not serialized.
When a specific
Messageis 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
@JsonViewannotation, 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 { @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
RestTemplateHTTP client or
MappingJackson2JsonViewby wrapping the value to serialize in a
MappingJacksonValueas shown in this
code sample.
JSONP
As described in thereference documentation, you can enable
JSONP for
@ResponseBodyand
ResponseEntitymethods by declaring an
@ControllerAdvicebean that extends
AbstractJsonpResponseBodyAdviceas shown below:
@ControllerAdvice public class JsonpAdvice extends AbstractJsonpResponseBodyAdvice { public JsonpAdvice() { super("callback"); } }
With such
@ControllerAdvicebean 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
MappingJackson2JsonViewwith a request that has a query parameter named jsonp or callback. The JSONP query parameter name(s) could be customized through the
jsonpParameterNamesproperty.
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-xmldependency 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-asldependency available to your project.
Customizing the Jackson ObjectMapper
Prior to Spring Framework 4.1.1, JacksonHttpMessageConverters were using
ObjectMapperdefault configuration. In order to provide a better and easily customizable default configuration, a new
Jackson2ObjectMapperBuilderhas been introduced. It is the JavaConfig equivalent of the well known
Jackson2ObjectMapperFactoryBeanused in XML configuration.
Jackson2ObjectMapperBuilderprovides a nice API to customize various Jackson settings
while retaining Spring Framework provided default ones. It also allows to create
ObjectMapperand
XmlMapperinstances based on the same configuration.
Both
Jackson2ObjectMapperBuilderand
Jackson2ObjectMapperFactoryBeandefine a better Jackson default configuration. For example, the
DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIESproperty 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_UNDERSCORESif you want to have your
userNamejava property translated to
user_namein 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 like
spring.jackson.serialization.indent_output=trueto
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 useJackson2ObjectMapperBuilderto customize the XML and JSON
HttpMessageConverters as shown bellow:
@Configuration @EnableWebMvc public 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: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
@Beanif you are using Spring Boot:
jackson-module-parameter-names: adds support for accessing parameter names (feature added in Java 8)
jackson-datatype-money:
javax.moneytypes (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 awareHandlerInstantiator(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
Entityretrieved from the database.
相关文章推荐
- js 定义函数的几种方法 以及如何调用
- d3.js—— 绘制二维数组的动态图表
- JSONException: There is a cycle in the hierarchy!解决Json死循环问题
- js模版解析
- 正则替换日期中间的符号
- js立即调用函数表达式
- 配置iis支持.json格式的文件
- [置顶] 常用js代码
- js模仿块级作用域
- 显示js对象的所有属性名称和属性值
- 关于html5与jsp页面同样的html代码展示的页面效果不一样的问题
- JS闭包
- d3.js——面积图表的制作
- js回车事件
- lodash:javascript工具库
- JS冒泡和闭包案例分析
- 页面传值对象 到controllerjs写法
- Javascript - 数组详解
- js导航二级下拉菜单
- jsp + js 文件上传获取进度