Spring Boot 2.0 读书笔记_06:Jackson

版权声明:未经博主本人同意,请勿私自转发分享。 https://blog.csdn.net/Nerver_77/article/details/84840890

4. Jackson

写在开头,在MVC框架中,Spring Boot 内置了 Jackson 来完成JSON的序列化和反序列化。

  • @ResponseBody 在Controller对应请求方法上就好了,自动将方法返回的对象序列化成JSON。

  • 序列化、反序列化方式
    Jackson是一个流行的高性能JavaBean到JSON的绑定工具,Jackson使用ObjectMapper类将POJO对象序列化成JSON字符串,也能将JSON字符串反序列化成POJO对象。

    方式 说明
    JsonParser 采用JsonParser来解析JSON,解析结果是一串Tokens。
    采用JSONGenerator来生成JSON,最底层方式。
    树遍历 (Tree Traversing) JSON被读入到JsonNode对象中,可以像操作XML DOM那样读取JSON
    DataBind 数据绑定方式,最简单直接的一种方式。
    有时候需要相关注解或序列化实现类来进行个性化序列化等操作

    对应用程序来讲,最常用的方式是DataBind,也就是将POJO对象转换成JSON字符串,或者解析JSON字符串并映射到POJO对象上。
    那么,如果没有现成的POJO对象做数据绑定的时候,也可以通过树遍历的方式来获取JSON数据。

  • Jackson 树遍历(Tree Traversing)
    树遍历方式通常适合没有POJO对象的JSON。

      @Autowired ObjectMapper mapper;
    
      @GetMapping("/readtree.json")
      public @ResponseBody String readtree() throws JsonProcessingException, IOException {
      	String json = "{\"name\":\"zhangsan\", \"id\":10}";
      	// JSON序列化
      	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数据:

    • axXXX:for example,asText、asBoolean、asInt etc… 读取JsonNode对应的值。
    • isArray:判断JsonNode是否是数组,如果是数组,则可以调用 get(i) 来进行遍历。
    • get(“key”):获取当前节点的子节点,返回JsonNode。
      注:JSON规范要求key是字符串,且要使用双引号。
  • ObjectMapper 序列化和反序列化

    • 序列化 POJO to JSON

        User user = mapper.readValue(json, User.class);
      
    • 反序列化 JSON to POJO

        String json = mapper.writeValueAsString(user);
      
    • 树模型和数据绑定都是基于流失操作完成的,即通过JsonParser类解析JSON,形成JsonToken流。

    • JsonParser 的解析结果包含了一些列JsonToken,JsonToken是一个枚举类型。列举常用的常量:

    枚举常量 说明
    START_OBJECT {
    END_OBJECT }
    START_ARRAY [
    END_ARRAY ]
    FIELD_NAME JSON key
    VALUE_STRING JSON value 字符串类型
    VALUE_NUMBER_INT JSON value 整型

    序列化简易流程:

      // 模拟JSON数据,Map形式 
      String json = "{\"name\":\"zhangsan\"}";
      // 定义暂存数据变量
      String key = null, value = null;
      /**
      * 开始解析JSON
      */ 	
      JsonFactory f = mapper.getFactory();
      JsonParser parser = f.createParser(json);
      // { -> START_OBJECT,忽略第一个Token
      JsonToken token = parser.nextToken();
      token = parser.nextToken();
      // JSON key  -> FIELD_NAME 保存至暂存数据变量key中
      if(token == JsonToken.FIELD_NAME) {
      	key = parser.getCurrentName();
      }
      token = parser.nextToken();
      // JSON value -> VALUE_STRING 保存至暂存数据变量value中
      value = parser.getValueAsString();
      // 关闭 parser
      parser.close();
      return key + " : " + value;
    

    判断Token类型后,通过getValueAsXXX获取其值,XXX是其值的类型。
    反序列化简易流程:

      JsonFactory f = mapper.getFactory();
      // 输出到 StringWriter
      StringWriter sw = new StringWriter();
      JsonGenerator g = f.createGenerator(sw);
      // 输出 {
      g.writeStartObject();
      // 输出数据
      g.writeStringField(key, value);
      // 输出 }
      g.writeEndObject();
      // 关闭 StringWriter
      g.colse();
      retrun sw.toString();
    
  • Jackson 常用注解

注解 说明 实例
@JsonProperty 作用在属性上,为JSON Key指定别名 @JsonProperty(“userName”)
private String name;
@JsonIgnore 作用在属性上,用来忽略此属性 @JsonIgnore
private String password;
@JsonIgnoreProperties 作用于类上,忽略一组属性 @JsonIgnoreProperties({“id”, “phone”})
public static class SamplePojo{…}
@JsonFormat 日期格式化 @JsonFormat(pattern = “yyyy-MM-dd”)
private Date date;

补充不常用注解:
@JsonSerialize 指定一个实现类来自定义序列化,类必须继承JsonSerializer

public static class UserSerializer extends JsonSerializer<User> {
  @Override
  public void serialize(User user, JsonGenerator jsonGenerator,
                        SerializerProvider serializerProvider) throws IOException {
    jsonGenerator.writeStartObject();
    jsonGenerator.writeStringField("user_name", user.getName());
    jsonGenerator.writeEndObject();
  }
}

JsonGenerator 对象是 Jackson 底层的序列化实现,上述代码中对name属性做了序列化,输出key形式上变更为:user_name。
使用@JsonSerialize注解需要制定对象的序列化方式,例如:

@JsonSerialize(using = UserSerializer.class)
public class User {
  ...
}

同样的,自定义反序列化,需要通过反序列化实现类继承JsonDeserializer,使用@JsonDeserialize注解制定对象反序列化方式。
@JsonView,作用在类或者属性上,用来序列化组。Spring MVC的Controller方法可以使用同样的@JsonView来序列化属于本组的设置。
对于User对象,有些情况下只需要返回id属性,有些情况需要返回id和name,因此User对象可以定义为如下:

public class User {
  public interface IdView {};
  public interface IdNameView extends IdView {};
  
  @JsonView(IdView.class)
  private Integer id;
  @JsonView(IdNameView.class)
  private String name;
  @JsonIgnore
  BigDecimal salary;
}

User定义了两个接口类,IdView、IdNameView(继承IDView接口)。这两个接口代表了两个序列化组的名称。
Spring MVC 的Controller方法运行使用@JsonView()指定一个序列化组名,被序列化的对象只有在该序列组中的属性才会被序列化。

@JsonView(User.IdView.class)
@RequestMapping("/id.json")
public @ResponseBody User queryIds() {
  User user = new User();
  user.setId(1);
  user.setName("hello");
  return user;
}

上述代码,只会输出id属性内容。更换成@JsonView(User.IdNameView.class)将输出id和name,因为组名IdView是IdNameView的父类。

  • 集合的反序列化
    Spring MVC的Controller方法中,可以对参数列表使用@RequestBody注解,将提交的JSON自动映射到方法参数上。
    注意是@RequestBody,是@RequestBody,是@RequestBody,不是@ResponseBody

    @RequestMapping("/addUser.json")
    public @ResponseBody String addUser(@RequestBody User user) {
      ...
      return user.toString();
    }
    

    通过Postman进行接口调用的时候需要注意:接收的是JSON请求

    在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Nerver_77/article/details/84840890
今日推荐