Spring Boot 之遇见JSON
MVC框架中,Spring Boot内置了jackson来完成JSON的序列化和反序列化操作,并且,在与其他技术集成的时候,如Redis、MongoDB、Elasticsearch等对象序列化,都可使用jackson来完成。
Spring Boot 之遇见JSON
Spring Boot中使用Jackson
在Controller中,方法注解为@ResponseBody,则自动将方法返回的对象序列化成JSON。
@Controller
@RequestMapping("/json")
public class JsonController(){
@Autowired UserService userService;
@GetMapping("/user/{id}.json")
public @ResponseBody User showUserInfo(@PathVariable Long id){
User user = userService.getUserById(id);
return user;
}
}
自定义ObjectMapper
使用Java Config来自定义一个ObjectMapper,使用@Bean来配置,如:
@Configuration
public class JacksonConf{
@Bean
public ObjectMapper getObjectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
return objectMapper;
}
}
获取当前时间:
@GetMapping("/now.json")
public @ResopnseBody Map datetime() {
Map map = new HashMap ();
map.put("time", new Date());
return map;
}
当访问now.json时,输出:
{"time": "2019-03-17 11:11:11"}
Jackson的三种使用方式
- 采用JsonParser来解析JSON,解析结果是一串Tokens,采用JsonGenerator来生成JSON,这是最底层的方式。
- 采用树遍历(Tree Traversing)方式,JSON被读入到JsonNode对象中,可以像操作XML DOM那样读取JSON。
- 采用DataBind方式,将POJO序列化成JSON,或者反序列化到POJO。
Jackson树遍历
树遍历通常适合没有POJO对应的JSON,如:
@Autowired ObjectMapper mapper;
@GetMapping("/readtree.json")
public @ResponseBody String readtree() throws JsonProcessingException,IOException{
String json = "{\"name\":\"aaa\",\"id\":10}";
JsonNode node = mapper.readTree(json);
String name = node.get("name").asText();
int id = node.get("id").asInt();
return "name:"+name+",id"+id;
}
readTree方法可以接受一个字符串或者字节数组、文件、InputStream等,返回JsonNode作为根节点。
JsonNode支持以下方法来读取JSON数据:
- asXXX,如asText、asBoolean、asInt等,读取JsonNode对应的值。
- isArray,用于判断JsonNode是否是数组,如果是数组,可以用get(i)来进行遍历,通过size()来获取长度。
- get(String),获取当前节点的子节点,返回JsonNode。
JSON规范要求Key是字符串,且用双引号
对象绑定
应用程序更多的是使用Java对象与JSON数据互相绑定,仅仅调用ObjectMapper的readValue来实现,如:
{"name":"aaa",age:10}
可以创建一个POJO对象来与JSON相对应:
public class User {
Long id;
String name;
// setter getter
}
然后使用readValue来反序列化上面的JSON字符串:
@GetMapping("/databind.json")
public @ResponseBody String databind() throws JsonProcessingException,IOException{
String json = "{\"name\":\"aaa\",\"id\":10}";
User user = mapper.readValue(json,User.class);
return "name:"+user.getName()+",id:"+user.getId();
}
将POJO序列化成JSON,使用mapper的writeValueAsString方法:
@GetMapping("/serialization.json")
public @ResponseBody String custom() throws JsonProcessingException {
User user = new User();
user.setId(11);
user.setName("hello");
String str = mapper.writeValueAsString(user);
return str;
}
mapper.writeValueAsString将对象序列化成JSON字符串,可以使用Jackson注解来对序列化的字段进行定制。
流式操作
树模型和数据绑定都是基于流式操作完成的,即通过JsonParser来解析JSON,形成JsonToken流,下面的代码是解析JSON:
@Autowired
ObjectMapper mapper;
@RequestMapping("/parser.html")
public @ResponseBody String parser() throws JsonParseException,IOException{
String json = "{\"name\":\"aaa\",\"id\":10}";
JsonFactory f = mapper.getFactory();
String key = null,value=null;
JsonParser parser = f.createParser(json);
JsonToken token = parser.nextToken();
if(token == JsonToken.FIELD_NAME){
key = parser.getCurrentName();
}
token = parser.nextToken();
value = parser.getValueAsString();
parser.close();
return key+","+value;
}
JsonParser的解析结果包含了一系列JsonToken,JsonToken是一个枚举类型,常用的START_OBJECT代表符号“{”;START_ARRAY和END_ARRAY代表"[“和”]",FIELD_NAME表示一个JSON Key;VALUE_STRING代表一个JSON Value,字符串类型;VALUE_NUMBER则表示一个整数类型。
判断Token的类型后,通过调用getValueAsXXX来获取其值,XXX是其值的类型。
@RequestMapping("/generator.html")
public @ResponseBody String generator() throws JsonParseException,IOException{
JsonFactory f = mapper.getFactory();
StringWriter sw = new StringWriter();
JsonGenerator g = f.createGenerator(sw);
g.writeStartObject();
g.writeStringField("name","aaa");
g.writeEndObject();
g.close();
return sw.toString();
}
Jackson注解
Jackson包含了很多注解,用来个性化序列化和反序列化,如:
@JsonProperty,作用在属性上,用来为JSON Key指定一个别名。
@JsonProperty("userName")
private String name
@JsonIgnore,作用在属性上,用来忽略此属性。
@JsonIgnore
private String pwd
@JsonIgnoreProperties,忽略一组属性,作用在类上;
@JsonIgnoreProperties
public static class SamplePojo{
}
@JsonAnySetter,标记在某个方法上,此方法接受Key、Value两个参数,用于JackSon在反序列化过程中,未找到的对应属性都调用此方法,通常用一个map来实现:
@JsonAnySetter
private void other( String property, Object value ) {
map.put(property,value);
}
@JsonAnyGetter,此注解标注在一个返回Map的方法上,JackSon会取出Map中的每一个值进行序列化。
Class Department {
Map map = new HashMap();
int id;
public Department(int id){
this.id = id;
map.put("newAttr",1);
}
@JsonAnyGetter
public Map<String,Object> getOtherProperties() {
return map;
}
}
Department,对象序列化的时候,其JSON类似:
{“id”:1,“newAttr”:1}
@JsonFormat,用于日期格式,
@JsonFormat(pattern = "yyyy-MM-dd HH-mm-ss")
private Date createDate;
@JsonNaming,用于指定一个命名策略,作用于类或者属性上。
@JsonSerialize,指定一个实现类来自定义序列化。类必须实现JsonSerializer接口。
@JsonDeserialize,用户自定义反序列化。
@JsonView,作用在类或者属性上,用来自定义一个序列化组。比如对于User对象,某些情况下只返回id,而某些情况下需要返回id和name;
public class User {
public interface IdView {};
public interface IdNameView extends IdView {};
@JsonView(IdView.class)
private Interger id;
@JsonView(IdNameView.class)
private String name;
}
集合的反序列化
在Spring MVC的Controller方法中,可以使用@RequestBody将提交的JSON自动映射到方法参数上,如:
@RequestMapping("/updateUsers.json")
public @ResponseBody String say(@RequestBody List<User> list){
StringBuilder sb = new StringBuilder();
for(User user:list){
sb.append(user.getName()).append(" ");
}
return sb.toString();
}
接受如下一个JSON请求,并自动映射到User对象上。
[
{
"name":"aaa",
"id":1
}
{
"name":"bbb",
"id":2
}
]
Spring Boot能自动识别出List对象包含的是User类,因为在方法中定义的泛型的类型会被保留在字节码中,所以Spring Boot能识别List包含的泛型类型从而能正确反序列化。
Spring Boot 之遇见JSON的更多相关文章
- spring boot @ResponseBody转换JSON 时 Date 类型处理方法,Jackson和FastJson两种方式,springboot 2.0.9配置fastjson不生效官方解决办法
spring boot @ResponseBody转换JSON 时 Date 类型处理方法 ,这里一共有两种不同解析方式(Jackson和FastJson两种方式,springboot我用的1.x的版 ...
- Spring Boot 之使用 Json 详解
Spring Boot 之使用 Json 详解 简介 Spring Boot 支持的 Json 库 Spring Web 中的序列化.反序列化 指定类的 Json 序列化.反序列化 @JsonTest ...
- Spring Boot Security And JSON Web Token
Spring Boot Security And JSON Web Token 说明 流程说明 何时生成和使用jwt,其实我们主要是token更有意义并携带一些信息 https://github.co ...
- Spring boot之返回json数据
1.步骤: 1. 编写实体类Demo 2. 编写getDemo()方法 3. 测试 2.项目构建 编写实体类Demo package com.kfit; /** * 这是一个测试实体类. */ pub ...
- Spring Boot HTTP over JSON 的错误码异常处理
摘要: 原创出处:www.bysocket.com 泥瓦匠BYSocket 希望转载,保留摘要,谢谢! “年轻人不要怕表现,要敢于出来表现,但还是那句话,要有正确的度,你的表现是分析问题和解决问题的能 ...
- Spring Boot默认的JSON解析框架设置
方案一:启动类继承WebMvcConfigurerAdapter,覆盖方法configureMessageConverters ... @SpringBootApplication public cl ...
- Spring boot中自定义Json参数解析器
转载请注明出处... 一.介绍 用过springMVC/spring boot的都清楚,在controller层接受参数,常用的都是两种接受方式,如下 /** * 请求路径 http://127.0. ...
- (4)Spring Boot使用别的json解析框架【从零开始学Spring Boot】
此文章已经废弃,请看新版的博客的完美解决方案: 78. Spring Boot完美使用FastJson解析JSON数据[从零开始学Spring Boot] http://412887952-qq-co ...
- spring boot 自己输出json数据
@RequestMapping("/json")public void json(HttpServletResponse response, Pager pager, TruckF ...
随机推荐
- python-scrapy爬取某招聘网站(二)
首先要准备python3+scrapy+pycharm 一.首先让我们了解一下网站 拉勾网https://www.lagou.com/ 和Boss直聘类似的网址设计方式,与智联招聘不同,它采用普通的页 ...
- Service Mesh——微服务中的流量管理中间件
Service Mesh--微服务中的流量管理中间件 摘自-https://zhuanlan.zhihu.com/p/28794062 Service mesh 与 Cloud Native Kube ...
- java异常相关说明(printStackTrace,fillInStackTrace等)
我们在实际场景中很容易catch(Exception e) 简单粗暴 这样写代码有几个问题 1.你无法细分具体异常 因为有时需要针对不同异常 产生不同的应对行为 2.直接exception 往往不会包 ...
- select机制
select机制 函数作用: 在一段时间指定的时间内,监听用户感兴趣的文件描述符上可读.可写和异常事件. 函数原型: #include <sys/time.h> #include < ...
- layer做阻塞式弹出层的方法
今天遇到一个问题: layer弹出一个confirm提示窗,然后confirm还没有点击对应的按钮的时候,就已经执行了后续代码,我这里做出的判断是,是否需要进行后续操作,但是因为layer.confi ...
- java面向对象的一些知识
(1)this和super关键字的用法 this表示调用本类实例方法和成员变量,this引用就是对一个对象的引用,如this.name 表示本类成员变量name,静态方法中不能使用this关键字. ...
- Redis缓存篇(一)Redis是如何工作的
Redis提供了高性能的数据存取功能,所以广泛应用在缓存场景中,既能有效地提升业务应用的响应速度,还可以避免把高并发压力发送到数据库层. 因为Redis用作缓存的普遍性以及它在业务应用中的重要作用,所 ...
- 容器编排系统K8s之节点污点和pod容忍度
前文我们了解了k8s上的kube-scheduler的工作方式,以及pod调度策略的定义:回顾请参考:https://www.cnblogs.com/qiuhom-1874/p/14243312.ht ...
- 【递归】P2386放苹果
题目相关 题目描述 把 m个同样的苹果放在 n个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法.(5,1,1 和 1,1,5 是同一种方法) 输入格式 第一行是测试数据的数目 t,以下每行 ...
- new ArrayList(0) 和 new ArrayList() 和一样吗?
第一感觉是一样的,盲猜后者调用了前者,并传入参数 0.然而,无论是 JDK 7 还是 JDK 8,这两个方法构造的结果都是不一样的.JDK 开发人员在这方面作了优化. JDK 7 在 Java 7 中 ...