14. 集成`JackJson`

1. 返回json

1. 依赖
  1. Spring Boot 默认集成JackJson,无需依赖

  2. SSM

    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.10.1</version>
    </dependency>
    
2. 简单使用
  1. 常用注解

    1. @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")

      • 修饰属性或者setter方法

      • 时间类型成员变量的入参以及序列化格式转化为字符串

      • 入参同样的作用:@DateTimeFormat(pattern = "yyyy-MM-dd") --> org.springframework.format.annotation.DateTimeFormat

      • 栗子

        @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
        private Date date;
        
    2. @JsonProperty

      • 修饰属性

      • 将成员变量序列化为另一个名称,反序列化时也只接受另一个名称的参数

      • 栗子

        @JsonProperty("sub_button")
        private List<WxMenuButtonBean> subButtons;
        
    3. @JsonAlias

      • 修饰属性

      • 反序列化时只接受另一个名称的参数,优先级在@JsonProperty之上

      • 栗子

        // 反序列化时,接受"subButtons"、"sub_button",序列化为 "sub_button"
        @JsonProperty("sub_button")
        @JsonAlias({"subButtons", "sub_button"})
        private List<WxMenuButtonBean> subButtons;
        
    4. @JsonIgnore

      • 修饰属性方法
      • 序列化/反序列化时忽略掉修饰的属性
    5. @JsonIgnoreProperties

      • 在序列化/反序列化时忽略掉某些属性

      • 可看作@JsonIgnore的批量操作

      • 当类似于代理类无法使用 @JsonIgnore,则可用@JsonIgnoreProperties

      • 栗子

        // 忽略"属性1", "属性2",忽略未知属性
        @JsonIgnoreProperties(value = {"属性1", "属性2"}, ignoreUnknown = true)
        
    6. @JsonSerialize(using = StdSerializer.class)

      • 自定义序列化时,修饰需要自定义序列化的类StdSerializer.class为自定义序列化类

      • 简写了以下的注册代码

        ObjectMapper mapper = new ObjectMapper();
        // Module
        SimpleModule module
                = new SimpleModule("name", new Version(1, 0, 0, null, null, null));
        module.addDeserializer(WxIndustryBean.class, new JsonDeserializer());
        // 注册
        mapper.registerModule(module);
        
      • 栗子:toJson()

        @Getter
        @Setter
        @JsonSerialize(using = WxIndustryBean.WxIndustryBeanSerializer.class)
        public class WxIndustryBean implements JsonService<WxIndustryBean> {
            private static final long serialVersionUID = -1277224438711154747L;
        
            @JsonAlias("primary_industry")
            private Industry primaryIndustry;
        
            @JsonAlias("secondary_industry")
            private Industry secondaryIndustry;
        
            private WxIndustryBean() {
            }
        
            @Override
            public String toJson() {
                ObjectMapper mapper = new ObjectMapper();
        //        // Module
        //        SimpleModule module = new SimpleModule();
        //        module.addSerializer(WxIndustryBean.class, new WxIndustryBeanSerializer());
        //        // 注册
        //        mapper.registerModule(module);
                
                // 使用了 @JsonSerialize(using = WxIndustryBean.WxIndustryBeanSerializer.class),可简写,忽略以上代码
                try {
                    return mapper.writeValueAsString(this);
                } catch (Exception e) {
                    throw new RuntimeException("WxIndustryBean 序列化失败");
                }
            }
        
            /**
             * 初始化
             *
             * @param primaryIndustryId   主行业 Id
             * @param secondaryIndustryId 副行业 Id
             * @return {@link WxIndustryBean}
             */
            public static WxIndustryBean getInstance(String primaryIndustryId, String secondaryIndustryId) {
                WxIndustryBean bean = new WxIndustryBean();
                bean.setPrimaryIndustry(Industry.getInstance(primaryIndustryId));
                bean.setSecondaryIndustry(Industry.getInstance(secondaryIndustryId));
                return bean;
            }
        
            /**
             * 微信公众号行业信息
             */
            @Data
            static class Industry implements Serializable {
                private static final long serialVersionUID = -3974402817176452594L;
        
                /**
                 * 公众号模板消息所属行业编号
                 */
                @JsonIgnore
                private String industryId;
        
                /**
                 * 主行业
                 */
                @JsonAlias("first_class")
                private String firstClass;
        
                /**
                 * 副行业
                 */
                @JsonAlias("second_class")
                private String secondClass;
        
                /**
                 * 初始化
                 *
                 * @param industryId 所属行业编号
                 * @return {@link Industry}
                 */
                static Industry getInstance(String industryId) {
                    if (StrUtil.isBlank(industryId)) {
                        throw new IllegalArgumentException("行业编号不能为空");
                    }
                    Industry industry = new Industry();
                    industry.setIndustryId(industryId);
                    return industry;
                }
            }
        
            /**
             * 序列化类
             */
            static class WxIndustryBeanSerializer extends StdSerializer<WxIndustryBean> {
                private static final long serialVersionUID = -2688346808314421783L;
        
                WxIndustryBeanSerializer() {
                    this(null);
                }
        
                protected WxIndustryBeanSerializer(Class<WxIndustryBean> t) {
                    super(t);
                }
        
                @Override
                public void serialize(WxIndustryBean value, JsonGenerator gen, SerializerProvider provider) throws IOException {
                    gen.writeStartObject();
        
                    Industry industry;
                    gen.writeStringField("industry_id1", Objects.nonNull(value) && Objects.nonNull(industry = value.getPrimaryIndustry()) ? industry.getIndustryId() : null);
                    gen.writeStringField("industry_id2", Objects.nonNull(value) && Objects.nonNull(industry = value.getSecondaryIndustry()) ? industry.getIndustryId() : null);
        
                    gen.writeEndObject();
                }
            }
        }
        
    7. @JsonDeserialize(using = StdDeserializer.class)

      • 自定义反序列化时,修饰需要自定义序列化的类StdDeserializer.class为自定义序列化类

      • 简写了以下注册代码

        ObjectMapper mapper = new ObjectMapper();
        // Module
        SimpleModule module
                = new SimpleModule("JsonDeserializer", new Version(1, 0, 0, null, null, null));
        module.addDeserializer(WxIndustryBean.class, new JsonDeserializer());
        // 注册
        mapper.registerModule(module);
        
      • @JsonSerialize(using = StdSerializer.class)使用类似

  2. 最常用Api是基于对象绑定ObjectMapper

    1. 规则

      • 如果字段的修饰符是public,则该字段可序列化和反序列化(不是标准写法)。
      • 如果字段的修饰符不是 public,但是它的getter方法和setter方法是public,则该字段可序列化和反序列化。getter 方法用于序列化setter 方法用于反序列化
      • 如果字段只有publicsetter方法,而无publicgetter方 法,则该字段只能用于反序列化
      • 如果想更改默认的序列化和反序列化规则,需要调用ObjectMappersetVisibility()方法。否则将会抛出InvalidDefinitionException异常。
      • getter、setter方法要遵循小驼峰命名法,否则可能出现属性的序列化、反序列化失败
    2. 常用配置

      ObjectMapper mapper = new ObjectMapper();
      // 忽略无法识别的字段
      mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
      // 在序列化时,忽略值为 null 的属性
      mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
      // 忽略值为默认值的属性
      // mapper.setDefaultPropertyInclusion(JsonInclude.Include.NON_DEFAULT);
      // 时间格式
      mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
      
    3. 序列化

      // 将对象序列化为字符串
      String writeValueAsString(Object value)
      
      // 将对象序列化为字节数组
      byte[] writeValueAsBytes(Object value)
      
      // 将对象序列化存储到文件
      writeValue(File resultFile, Object value)
      
    4. 反序列化

      • 反序列化时要求对象必须有默认构造方法,否则抛出InvalidDefinitionException异常
      // Json 序列化为 T 对象
      <T> T readValue(String content, Class<T> valueType)
      
      // byte[] 序列化为 T 对象
      <T> T readValue(byte[] src, Class<T> valueType)
      
      // 生成 JSONNode 对象
      // 利用 jsonNode.get() 方法读取
      JsonNode readTree(String content)
      
      // 利用 TypeReference 可指定泛型,生成 Map、List 等对象
      <T> T readValue(String content, TypeReference<T> valueTypeRef)
      
      // 也可指定泛型,生成 Map、List 等对象,少用
      <T> T readValue(String content, JavaType valueType)
      
      • 栗子
      String json = "{\"name\": \"haha\", \"phone\": 123}";
      ObjectMapper mapper = new ObjectMapper();
      
      // JsonNode readTree(String content)
      JsonNode jsonNode = mapper.readTree(json);
      System.out.println(jsonNode.get("name").asText());
      
      // <T> T readValue(String content, TypeReference<T> valueTypeRef)
      Map<String, Object> map = mapper.readValue(json, new TypeReference<Map<String, Object>>() {
      });
      map.forEach((k, v) -> System.out.println(k + " = " + v));
      
      // <T> T readValue(String content, JavaType valueType)
      Map<String, Object> o = mapper.readValue(json, TypeFactory.defaultInstance().constructMapType(Map.class, String.class, Object.class));
      o.forEach((k, v) -> System.out.println(k + " = " + v));
      
    5. 工具类

      import com.fasterxml.jackson.annotation.JsonInclude;
      import com.fasterxml.jackson.core.type.TypeReference;
      import com.fasterxml.jackson.databind.DeserializationFeature;
      import com.fasterxml.jackson.databind.JsonNode;
      import com.fasterxml.jackson.databind.ObjectMapper;
      import com.fasterxml.jackson.databind.type.TypeFactory;
      import lombok.extern.slf4j.Slf4j;
      
      import java.text.SimpleDateFormat;
      import java.util.List;
      import java.util.Map;
      import java.util.Set;
      
      /**
       * Json 相关工具类
       *
       * @author sheng_zs@126.com
       * @date 2021-08-05 15:57
       */
      @Slf4j
      public class JsonUtils {
          private static final ObjectMapper MAPPER;
      
          static {
              ObjectMapper mapper = new ObjectMapper();
              // 忽略无法识别的字段
              mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
              // 在序列化时,忽略值为 null 的属性
              mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
              // 忽略值为默认值的属性
      //        mapper.setDefaultPropertyInclusion(JsonInclude.Include.NON_DEFAULT);
              // 时间格式
              mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
              MAPPER = mapper;
          }
      
          /**
           * 将 json 字符串转化为 Java Bean
           *
           * @param target json 字符串
           * @param cls    Java Bean 的字节码对象
           * @param <T>    泛型
           * @return Java Bean
           */
          public static <T> T readValue(String target, Class<T> cls) {
              try {
                  return MAPPER.readValue(target, cls);
              } catch (Exception e) {
                  log.error("json [{}] to bean [{}] 错误", target, cls);
                  throw new RuntimeException(e.getMessage());
              }
          }
      
          /**
           * <p>将 json 字符串转化为 T 对象</p><br>
           * 栗子:
           * <ol>
           *     <li>Set<String> set = readValue("[\"1\"]", new TypeReference<Set<String>>() {});</li>
           *     <li>List<String> list = readValue("[\"1\"]", new TypeReference<List<String>>() {});</li>
           *     <li>Map<String, Object> map = readValue("{\"1\": \"a\"}", new TypeReference<Map<String, Object>>() {});</li>
           * </ol>
           *
           * @param target json
           * @param type   {@link TypeReference} new TypeReference<T>{}
           * @param <T>    泛型,转化的对象类型
           * @return T
           */
          public static <T> T readValue(String target, TypeReference<T> type) {
              try {
                  return MAPPER.readValue(target, type);
              } catch (Exception e) {
                  log.error("json [{}] to List [e:{}] 错误", target, type);
                  throw new RuntimeException(e.getMessage());
              }
          }
      
          /**
           * <p>将 json 字符串转化为 Map<K, V> 对象</p>
           *
           * @param target json 字符串
           * @param kCls   key 类型
           * @param vCls   value 类型
           * @param <K>    key 泛型
           * @param <V>    value 泛型
           * @return Map<K, V>
           */
          public static <K, V> Map<K, V> readValueAsMap(String target, Class<K> kCls, Class<V> vCls) {
              try {
                  JsonNode jsonNode = MAPPER.readTree(target);
                  return MAPPER.readValue(target, TypeFactory.defaultInstance().constructMapType(Map.class, kCls, vCls));
              } catch (Exception e) {
                  log.error("json [{}] to Map [k:{}, v:{}] 错误", target, kCls, vCls);
                  throw new RuntimeException(e.getMessage());
              }
          }
      
          /**
           * <p>将 json 字符串转化为 Map<String, Object> 对象</p>
           *
           * @param target json 字符串
           * @return Map<String, Object>
           */
          public static Map<String, Object> readValueAsMap(String target) {
              return readValue(target, new TypeReference<Map<String, Object>>() {
              });
          }
      
          /**
           * <p>将 json 字符串转化为 List<E> 对象</p>
           *
           * @param target json 字符串
           * @param eCls   成员字节码对象
           * @param <E>    成员 泛型
           * @return List<E>
           */
          public static <E> List<E> readValueAsList(String target, Class<E> eCls) {
              try {
                  return MAPPER.readValue(target, TypeFactory.defaultInstance().constructCollectionType(List.class, eCls));
              } catch (Exception e) {
                  log.error("json [{}] to List [e:{}] 错误", target, eCls);
                  throw new RuntimeException(e.getMessage());
              }
          }
      
          /**
           * <p>将 json 字符串转化为 Set<E> 对象</p>
           *
           * @param target json 字符串
           * @param eCls   成员字节码对象
           * @param <E>    成员 泛型
           * @return Set<E>
           */
          public static <E> Set<E> readValueAsSet(String target, Class<E> eCls) {
              try {
                  return MAPPER.readValue(target, TypeFactory.defaultInstance().constructCollectionType(Set.class, eCls));
              } catch (Exception e) {
                  log.error("json [{}] to Set [e:{}] 错误", target, eCls);
                  throw new RuntimeException(e.getMessage());
              }
          }
      
          /**
           * 将 json 字符串转化为 JsonNode 对象
           *
           * @param target json 字符串
           * @return {@link JsonNode}
           */
          public static JsonNode readTree(String target) {
              try {
                  return MAPPER.readTree(target);
              } catch (Exception e) {
                  log.error("json [{}] to JsonNode 错误", target);
                  throw new RuntimeException(e.getMessage());
              }
          }
      
          /**
           * 将 Java Bean o 转化为 字符串
           *
           * @param o Java Bean
           * @return Json 字符串
           */
          public static String writeValueAsString(Object o) {
              try {
                  return MAPPER.writeValueAsString(o);
              } catch (Exception e) {
                  log.error("bean [{}] to json 错误", o);
                  throw new RuntimeException(e.getMessage());
              }
          }
      
          /**
           * 将 Java Bean o 转化为 byte[]
           *
           * @param o Java Bean
           * @return 字节数组
           */
          public static byte[] writeValueAsBytes(Object o) {
              try {
                  return MAPPER.writeValueAsBytes(o);
              } catch (Exception e) {
                  log.error("bean [{}] to byte[] 错误", o);
                  throw new RuntimeException(e.getMessage());
              }
          }
      }
      
  3. 自定义序列化和反序列化

    1. 序列化

      • 继承 StdSerializer
      • 重写 serialize() 方法
      • 利用 JsonGenerator 生成 JSON
      import com.fasterxml.jackson.core.JsonGenerator;
      import com.fasterxml.jackson.core.JsonProcessingException;
      import com.fasterxml.jackson.core.Version;
      import com.fasterxml.jackson.databind.ObjectMapper;
      import com.fasterxml.jackson.databind.SerializerProvider;
      import com.fasterxml.jackson.databind.module.SimpleModule;
      import com.fasterxml.jackson.databind.ser.std.StdSerializer;
      import lombok.AllArgsConstructor;
      import lombok.Data;
      
      import java.io.IOException;
      
      /**
       * @author sheng_zs@126.com
       * @date 2021-08-06 14:46
       */
      public class Test {
          public static void main(String[] args) throws JsonProcessingException {
              /*
                  要想调用 自定义序列化 类,需注册到 ObjectMapper 的 Module
               */
              ObjectMapper mapper = new ObjectMapper();
              // Module
              SimpleModule module
                      = new SimpleModule("JsonSerializerTest", new Version(1, 0, 0, null, null, null));
              module.addSerializer(TestBean.class, new JsonSerializerTest());
              // 注册
              mapper.registerModule(module);
      
              TestBean haha = new TestBean("haha", "11");
              String s = mapper.writeValueAsString(haha);
              System.out.println(s);
          }
      }
      
      class JsonSerializerTest extends StdSerializer<TestBean> {
          public JsonSerializerTest() {
              this(null);
          }
      
          protected JsonSerializerTest(Class<TestBean> t) {
              super(t);
          }
      
          @Override
          public void serialize(TestBean value, JsonGenerator gen, SerializerProvider provider) throws IOException {
              gen.writeStartObject();
              gen.writeStringField("name", "姓名:" + value.getName() + ",测试自定义序列化");
              gen.writeStringField("phone", "手机:" + value.getPhone() + ",哈哈的手机号,不填也可");
              gen.writeEndObject();
          }
      }
      
      @Data
      @NoArgsConstructor
      @AllArgsConstructor
      @ToString
      class TestBean {
          private String name;
          private String phone;
      }
      
    2. 反序列化

      • 继承 StdDeserializer
      • 重写 deserialize() 方法
      • 利用 JsonGenerator 读取 JSON
      import com.fasterxml.jackson.core.JsonParser;
      import com.fasterxml.jackson.core.JsonProcessingException;
      import com.fasterxml.jackson.core.Version;
      import com.fasterxml.jackson.databind.DeserializationContext;
      import com.fasterxml.jackson.databind.JsonNode;
      import com.fasterxml.jackson.databind.ObjectMapper;
      import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
      import com.fasterxml.jackson.databind.module.SimpleModule;
      import lombok.AllArgsConstructor;
      import lombok.Data;
      import lombok.NoArgsConstructor;
      import lombok.ToString;
      
      import java.io.IOException;
      
      /**
       * @author sheng_zs@126.com
       * @date 2021-08-06 14:46
       */
      public class Test {
          public static void main(String[] args) throws JsonProcessingException {
              /*
                  要想调用 自定义反序列化 类,需注册到 ObjectMapper 的 Module
               */
              ObjectMapper mapper = new ObjectMapper();
              // Module
              SimpleModule module
                      = new SimpleModule("JsonDeserializerTest", new Version(1, 0, 0, null, null, null));
              module.addDeserializer(TestBean.class, new JsonDeserializerTest());
              // 注册
              mapper.registerModule(module);
      
              String json = "{\"name\":\"姓名:haha,测试自定义序列化\",\"phone\":\"手机:11,哈哈的手机号,不填也可\"}";
              TestBean bean = mapper.readValue(json, TestBean.class);
              System.out.println(bean);
          }
      }
      
      class JsonDeserializerTest extends StdDeserializer<TestBean> {
          public JsonDeserializerTest() {
              this(null);
          }
      
          protected JsonDeserializerTest(Class<?> vc) {
              super(vc);
          }
      
          @Override
          public TestBean deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
              /*
                  1. 通过 JsonNode 把 JSON 读取到一个树形结构中
                  2. 然后通过 JsonNode 的 get 方法将对应字段读取出来
                  3. 然后生成新的 Java 对象,并返回
               */
              TestBean testBean = new TestBean();
              JsonNode node = p.getCodec().readTree(p);
              String name = node.get("name").asText();
              testBean.setName((name = name.replaceFirst("姓名:", "")).substring(0, name.lastIndexOf(",测试自定义序列化")));
              String phone = node.get("phone").asText();
              testBean.setPhone((phone = phone.replaceFirst("手机:", "")).substring(0, phone.lastIndexOf(",哈哈的手机号,不填也可")));
              return testBean;
          }
      }
      
      @Data
      @NoArgsConstructor
      @AllArgsConstructor
      @ToString
      class TestBean {
          private String name;
          private String phone;
      }        
      

2. 返回xml

1. 依赖
<dependency>
    <groupId>com.fasterxml.jackson.dataformat</groupId>
    <artifactId>jackson-dataformat-xml</artifactId>
    <version>2.10.1</version>
</dependency>
2. 简单使用
  1. 实体类
    @Data
    @JacksonXmlRootElement(localName = "哈哈")
    public class TestDTO {
        @JacksonXmlProperty(localName = "Nihao")
        private String name;
    
        @JacksonXmlProperty(localName = "地址")
        private String addr;
    
        @JacksonXmlProperty(localName = "年龄")
        private Integer age;
    }
    
  2. controller
    @PostMapping(produces = MediaType.APPLICATION_XML_VALUE)
    public Object h(@RequestBody TestDTO dto) {
        System.out.println(dto);
        return dto;
    }
    
  3. 结果
    在这里插入图片描述
  • @JacksonXmlRootElement修饰根标签,传入的时候可以按照原有的类名,也可以按照属性localName的值
  • @JacksonXmlProperty修饰属性,传入的时候必须按照属性localName的值
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值