zoukankan      html  css  js  c++  java
  • spring学习笔记---Jackson的使用和定制

    http://www.cnblogs.com/mumuxinfei/p/4761374.html

    ****************************************

    前言:
      JAVA总是把实体对象(数据库/Nosql等)转换为POJO对象再处理, 虽然有各类框架予以强力支持. 但实体对象和POJO, 由于"饮食习惯", "民族特色", "地域区别"等等差异, 需要有些定制需求, 使得能够完美的映射. 这个性化定制需求, 包括名称/时间格式/字段过滤等等约定.
      springmvc的学习笔记系列:
      • idea创建springmvc项目
      • 面向移动端支持REST API
      本文讲讲述如何把pojo对象转化为约定好的json数据格式. 权当笔记.

    疑问篇:
      springmvc在使用注解@ResponseBody返回一个POJO对象时, 其内部会借助Jackson来完成POJO转化为JSON的工作.
      比如对于如下的POJO类:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    public class Message {
     
      private String userId; // 用户id
     
      private String message; // 消息实体
     
      private Date timestamp; // 时间信息, yyyy-MM-dd HH:mm:ss
     
      private String extra; // 额外附带信息
     
    }

      其最终讲转换为如下的json格式:
      
      如果开发者需要如下需求:
      1). json实体的key命名规则, 全小写化, 不同单词以"_"字符连接.
      2). 返回时间字段, 需满足"yyyy-MM-dd HH:mm:ss"格式
      3). 省略掉extra字段
      由此可见我们的最终目标是:

    1
    {"user_id":"1001","message":"message","timestamp":"2015-08-31 12:16:30"}

    解决篇:
      • 重命名
      jackson对重命名的处理, 引入注解JsonProperty来实现. 其对单个属性配置有效.

    1
    2
    @JsonProperty(value="user_id")
    private String userId; // 用户id

      注: value属性设置为用户想要的命名即可.
      当然还有另一种方式注解方式, 是JsonNaming, 其修饰于POJO类上. 用于对所有属性, 进行统一的命名转换.

    1
    2
    3
    4
    @JsonNaming(PropertyNamingStrategy.LowerCaseWithUnderscoresStrategy.class)
    public class Message {
      ...
    }

      注: PropertyNamingStrategy就非常漂亮地把所有的类属性名称都转换为小写, 同时单词(驼峰命令法)之间使用'_'字符来分割.
      自定义的Strategy类, 需要实现如下抽象类:

    1
    2
    3
    4
    5
    public abstract class PropertyNamingStrategy implements Serializable {
      public abstract static class PropertyNamingStrategyBase extends PropertyNamingStrategy {
        public abstract String translate(String var1);
      }
    }

      • 字段可见性
      过滤某些字段属性, jackson引入了注解JsonIgnore. 其对单个属性生效.

    1
    2
    @JsonIgnore
    private String extra; // 额外附带信息

      还有另外一种方式, 是采用JsonIgnoreProperties, 其修饰POJO类, 指定一组需要忽略的字段.

    1
    2
    3
    4
    5
    // *) 字典{}内是property name列表
    @JsonIgnoreProperties({"extra", "extra1", "extra2"})
    public class Message {
      ...
    }

      • 自定义序列化/反序列化
      jackson采用@JsonSerialize@JsonDeserialize来实现自定义序列化/反序列化的实现. 如之前的时间字段作为例子.
      定义时间序列化的实现类.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    public class Message {
     
      @JsonSerialize(using=DemoDateSerializer.class)
      @JsonDeserialize(using=DemoDateDeserializer.class)
      private Date timestamp; // 时间信息, yyyy-MM-dd HH:mm:ss
     
    }
     
    // *) JSON的序列化类
    class DemoDateSerializer extends JsonSerializer<Date> {
      @Override
      public void serialize(Date value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        jgen.writeString(dateFormat.format(value));
      }
    }
     
    // *) JSON的反序列化类
    class DemoDateDeserializer extends JsonDeserializer<Date> {
      @Override
      public Date deserialize(JsonParser jp, DeserializationContext dctx) throws IOException, JsonProcessingException {
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
          return dateFormat.parse(jp.getValueAsString());
        } catch (ParseException e) {
          e.printStackTrace();
        } finally {
        }
        return null;
      }
    }

      除了常规的时间格式转换, 还能正则提取等功能. 序列化和反序列化的自定义, 使得Jackson更加的强大. 犹如hive中的UDF函数.

    实验效果:
      最终的定义的类修改如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    public class Message {
     
      @JsonProperty(value="user_id")
      private String userId; // 用户id
     
      private String message; // 消息实体
     
      @JsonSerialize(using=DemoDateSerializer.class)
      @JsonDeserialize(using=DemoDateDeserializer.class)
      private Date timestamp; // 时间信息, yyyy-MM-dd HH:mm:ss
     
      @JsonIgnore
      private String extra; // 额外附带信息
     
    }

      最终的效果如图所示:
      
      与最初期望的效果保持一致, 值得小小庆祝一下.

    总结:
      jackson还有很多高阶的用法, 比如破除循环引用的处理机制, 多类别的处理等等. 这边暂时忽略, 本文参考了博文"jackson annotations注解详解" , 深表敬意和感谢. 

    写在最后:
      
    如果你觉得这篇文章对你有帮助, 请小小打赏下. 其实我想试试, 看看写博客能否给自己带来一点小小的收益. 无论多少, 都是对楼主一种由衷的肯定.

  • 相关阅读:
    本地excel/csv文件-->hive-->mysql
    Beeline连接报错:Could not open client transport with JDBC Uri: jdbc:hive2://localhost:10000/default
    软件设计——抽象工厂模式之人与肤色 c++
    软件设计——抽象工厂模式之人与肤色
    软件设计——工厂方法模式之加密算法
    用idea实现对hdfs的部分操作
    关于将hive数据仓库中数据导出到mysql的中文乱码问题
    10月份阅读笔记二
    10月份阅读笔记一
    工厂方法模式实现DES和IDEA加密算法
  • 原文地址:https://www.cnblogs.com/zhao1949/p/6276757.html
Copyright © 2011-2022 走看看