Java Jackson 序列化与反序列化

  • 测试类

    • @Data
      public abstract class Animal {
          private String name;
      }
      
      public class Elephant extends Animal{
      }
      
      public class Monkey extends Animal{
      }
      
      Elephant elephant = new Elephant();
      elephant.setName("大象精");
      
      Monkey monkey = new Monkey();
      monkey.setName("孙悟空");
      
      ObjectMapper objectMapper = new ObjectMapper();
      System.out.println(objectMapper.writeValueAsString(elephant));
      System.out.println(objectMapper.writeValueAsString(monkey));
      
    • 输出

      {"name":"大象精"}
      {"name":"孙悟空"}
      
    • 原理

      • jackson 会获取 field 对应的 get 方法方法名,比如 getxxx,然后进行将 get 进行截断,变成xxx,即为对应的key

      • 注意大写转小写问题

        • 为避免,在field上加@JsonProperty , 在get set 上加@JsonIgnore
  • @JsonTypeInfo注解开启多态处理

    • 使用@class作为限定名

    • @JsonTypeInfo(
          use=Id.CLASS
      )
      public abstract class Animal {
          private String name;
          //忽略getter和setter
      }
      
      # 序列化
      # {"@class":"com.tinylynn.springboot.json.type.Elephant","name":"大象精"}
      # {"@class":"com.tinylynn.springboot.json.type.Monkey","name":"孙悟空"}
      
      
      
    • JsonTypeInfo.Id.NAME, 默认添加@type属性(使用简写@type+简写类名作为限定名)

      {"@type":"Elephant","name":"大象精"}
      {"@type":"Monkey","name":"孙悟空"}
      
    • JsonTypeInfo.As.WRAPPER_OBJECT:作为一个包装的对象
      
      @JsonTypeInfo(
          use=Id.NAME,
          include=As.WRAPPER_OBJECT
      )
      public abstract class Animal {
          //...
      }
      {"Elephant":{"name":"大象精"}}
      {"Monkey":{"name":"孙悟空"}}
      

      作为包装对象

    • WRAPPER_ARRAY 作为数组
      ["Elephant",{"name":"大象精"}]
      ["Monkey",{"name":"孙悟空"}]
      

      作为数组

    • @Data
      public class Zoo {
          @JsonTypeInfo(use=Id.NAME,include=As.EXTERNAL_PROPERTY)
          # EXTERNAL_PROPERTY 把该变量作为本类的额外属性
          private Animal animal;
          //动物园名称
          private String name;
      }
      
      Zoo zoo = new Zoo();
      zoo.setName("只有一只大象的动物园");
      zoo.setAnimal(elephant);
      System.out.println(objectMapper.writeValueAsString(zoo));
      
      # animal的额外属性"@type":"Elephant"
      {"animal":{"name":"大象精"},"@type":"Elephant","name":"只有一只大象的动物园"}
      

      作为一个额外的属性,跟POJO同级,只能用于属性,如何作用于类则跟JsonTypeInfo.As.PROPERTY是相同效果

    • include=JsonTypeInfo.As.PROPERTY

      • 作为POJO的属性出现(序列化后在POJO的属性位置,在一个大括号内)
      • 默认
    • property = "type"

      • @JsonTypeInfo(use = JsonTypeInfo.Id.NAME
            property = "type"
        )
        

        @type换为type

    • include= JsonTypeInfo.As.EXISTING_PROPERTY + property="type"

      • @JsonTypeInfo(
                include= JsonTypeInfo.As.EXISTING_PROPERTY,
                property="type",
                use= JsonTypeInfo.Id.NAME
        )
        @Data
        public abstract class Animal {
            private String name;
            private String type;
        }
        # 测试
        Elephant elephant = new Elephant();
        elephant.setName("大象精");
        elephant.setType("ele");
        
        Monkey monkey = new Monkey();
        monkey.setName("孙悟空");
        monkey.setType("mon");
        
        System.out.println(objectMapper.writeValueAsString(elephant));
        System.out.println(objectMapper.writeValueAsString(monkey));
        
        #结果
        {"name":"大象精","type":"ele"}
        {"name":"孙悟空","type":"mon"}
        

        使用已有属性type作为序列化key

        注意不可以为property=“name”, 序列化后反序列化主key不论如何都是type

    • visible(可选):

      • 定义识别码在反序列化时是否保留(不管false或true都不影响序列化)。默认是false,表示Jackson可以将识别码识别为类型后就删除。
  • @JsonSubTypes 反序列化

    • 使用默认@type,不设置name,使用默认匹配方法

    • # 基类
      @JsonTypeInfo(
              use = JsonTypeInfo.Id.NAME
      )
      @JsonSubTypes({ //设置对应子类的识别码值
              @JsonSubTypes.Type(value = Monkey.class) ,
              @JsonSubTypes.Type(value = Elephant.class)
      })
      @Data
      public abstract class Animal {
          private String name;
      }
      # 子类
      class Elephant extends Animal{
      }
      class Monkey extends Animal{
      }
      
      # 测试
      Elephant elephant = new Elephant();
      elephant.setName("大象精");
      
      Monkey monkey = new Monkey();
      monkey.setName("孙悟空");
      
      ObjectMapper objectMapper = new ObjectMapper();
      # 序列化
      String elephonJson = objectMapper.writeValueAsString(elephant);
      String monkeyJson = objectMapper.writeValueAsString(monkey);
      System.out.println(objectMapper.writeValueAsString(elephonJson));
      System.out.println(objectMapper.writeValueAsString(monkeyJson));
      # 结果
      "{\"@type\":\"大象\",\"name\":\"大象精\"}"
      "{\"@type\":\"猴子\",\"name\":\"孙悟空\"}"
      # 此处@typeJsonTypeInfo.Id.NAME所带属性
      
      # 反序列化
      Animal elephantFromJson = objectMapper.readValue(elephonJson, Animal.class);
      System.out.println(elephantFromJson instanceof Elephant);
      elephantFromJson.name = "大象精"
      # 结果
      true
      # 根据@JsonSubTypes.Type(value = Elephant.class) type的类名比较
      
    • 使用指定name匹配

      include= JsonTypeInfo.As.EXISTING_PROPERTY + property + @JsonSubTypes.type.name

      name匹配property的type对应的属性,同时value=elephant.class也匹配

      @JsonTypeInfo(
              include= JsonTypeInfo.As.EXISTING_PROPERTY,
              property="type",
              use= JsonTypeInfo.Id.NAME,
              visible = true
      )
      @JsonSubTypes({ //设置对应子类的识别码值
              @JsonSubTypes.Type(value = Elephant.class, name = "ele")
      })
      @Data
      public abstract class Animal {
          private String name;
          private String type;
      }
      
      # 测试序列化
      Elephant elephant = new Elephant();
      elephant.setName("大象精");
      elephant.setType("ele");
      ObjectMapper objectMapper = new ObjectMapper();
      String elephonJson = objectMapper.writeValueAsString(elephant);
      # 结果
      # {"name":"大象精","type":"ele"}
      
      # 测试反序列化
      Elephant elephantFromJson = objectMapper.readValue(elephonJson, Elephant.class);
      System.out.println(elephantFromJson);
      # 结果
      # Animal(name=大象精, type=ele)
      
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值