专栏首页大数据技术与应用实战放弃fastjson,拥抱Jackson

放弃fastjson,拥抱Jackson

  • json object操作
  • 序列化操作
  • 反序列化
  • 日期类型反序列化
  • 自定义反序列化
  • 枚举类型反序列化

背景

最近由于阿里的fastjson频繁爆出安全漏洞,为了避免后续升级上线的烦恼,决定弃用fastjson,使用Jackson,把现有项目中的fastjson都换成了Jackson,由于很多写法上有些不同,所以在这里把这些改过的东西做一下笔记。

常用操作

首先引入相关的pom

    <properties>
        <jackson.version>2.11.0</jackson.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>${jackson.version}</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>${jackson.version}</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>${jackson.version}</version>
        </dependency>
    </dependencies>

json object操作

当我们需要一个json对象和json数组的时候,我们可以使用下面的方法来构造ObjectNode和ArrayNode,类似fastjson中的JSONObject和JSONArray。

 @Test
 public void testJsonObject(){
  ObjectMapper mapper = new ObjectMapper();
  ObjectNode json = mapper.createObjectNode();
  json.put("name", "Tom");
  json.put("age", 1);
  System.out.println(json);

  ArrayNode jsonNodes = mapper.createArrayNode();
  jsonNodes.add(json);
  System.out.println(jsonNodes);
 }

序列化操作

序列化操作就是将Java对象转化成json,简单的语法如下:

 @Test
 public void testSerialize() throws JsonProcessingException{
  User user = new User();
  user.setAge(1);
  user.setName("zhangsan");
  user.setGender(GENDER.MALE);
  user.setBirthday(new Date());
  ObjectMapper mapper = new ObjectMapper();
  String s = mapper.writeValueAsString(user);
  System.out.println(s);
 }

普通的String和int类型没有什么疑问,我们这里涉及了两个特殊类型,一个是Date,还有一个是枚举。 日期类型我们是通过注解@JsonFormat对日期类型做了格式化,可以控制输出的日期格式。

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
private Date birthday;

枚举类型,我们通过注解@JsonValue来控制输出哪个字段。

      @JsonValue
  public String getName(){
   return name;
  }

反序列化

反序列化就是将json转化成Java对象,语法如下:

 @Test
 public void testDeSerialize() throws JsonProcessingException{
  String json = "{\"name\":\"zhangsan\",\"age\":10}";
  ObjectMapper mapper = new ObjectMapper();
  User user = mapper.readValue(json, User.class);
  System.out.println(user);
 }

日期类型反序列化

对于Date类型,目前支持以下的格式:

  • long类型的时间戳
  • 通过@JsonFormat 注解指定类型格式:yyyy-MM-dd HH:mm:ss
 @Test
 public void testDeSerializeDate() throws JsonProcessingException{
  String json = "{\"name\":\"zhangsan\",\"age\":10,\"birthday\":1592800446397}";
  ObjectMapper mapper = new ObjectMapper();
  User user = mapper.readValue(json, User.class);
  System.out.println(user);

  String json1 = "{\"name\":\"zhangsan\",\"age\":10,\"birthday\":\"2020-01-01 12:13:14\"}";
  User user1 = mapper.readValue(json1, User.class);
  System.out.println(user1);

 }

自定义反序列化

有时候系统提供的反序列化方式不能满足我们的需求,我们可以自定义一些方法来满足我们个性化的需求,我们以一个日期为例,讲讲如何自定义反序列化。

首先我们在对应的字段上通过注解@JsonDeserialize来指定反序列化的类

@JsonDeserialize(using = CustomDeserializerDate.class)
    private Date birthday_custom;

自定义的序列化类继承抽象类StdDeserializer,此外我们还要添加一个无参构造方法,否则会报错。 在deserialize方法里我们实现反序列化的逻辑.

   public static class CustomDeserializerDate extends StdDeserializer<Date>{

    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    protected CustomDeserializerDate(Class<?> vc){
     super(vc);
    }

    //需要一个无参构造方法,否则会报错
    public CustomDeserializerDate(){
     this(null);
    }

    @Override
    public Date deserialize(
      JsonParser p,
      DeserializationContext ctxt) throws IOException{
     String date = p.getText();
     try {
      return sdf.parse(date);
     } catch (ParseException e){
      e.printStackTrace();
     }
     return null;
    }
   }

枚举类型反序列化

最后我们讲一下枚举类型的反序列化

如下代码所示,我们通过注解@JsonCreator来处理枚举反序列化,该方法接收一个int类型的参数,也就是枚举的value值,返回枚举类型GENDER。如果没找到,则返回null.

 public static enum GENDER{
  MALE("男", 1), FEMALE("女", 0);
  private String name;
  private int value;

  @JsonCreator
  public static GENDER getGenderById(int value){
   for (GENDER c: GENDER.values()){
    if (c.getValue() == value){
     return c;
    }
   }
   return null;
  }
  
  ..........
   }

完整代码请参考:https://github.com/zhangjun0x01/bigdata-examples/blob/master/java/src/main/java/json/JacksonTest.java

本文分享自微信公众号 - 大数据技术与应用实战(bigdata_bigdata),作者:zhangjun

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-06-23

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • flink实战教程-使用set实时计算当天网站uv

    对于web网站,我们一般会有这样的需求,实时的计算出来当天网站的uv,尽可能快的展示出来。今天我们就讲一下基于java的set集合做一下实时uv的统计。

    大数据技术与应用实战
  • flink教程-详解flink 1.11 中的CDC (Change Data Capture)

    CDC,Change Data Capture,变更数据获取的简称,使用CDC我们可以从数据库中获取已提交的更改并将这些更改发送到下游,供下游使用。这些变更可以...

    大数据技术与应用实战
  • flink教程-flink 1.11 使用sql将流式数据写入hive

    上一篇介绍了使用sql将流式数据写入文件系统,这次我们来介绍下使用sql将文件写入hive,对于如果想写入已经存在的hive表,则至少需要添加以下两个属性. ...

    大数据技术与应用实战
  • 智能合约初探:概念与演变

    自2009年比特币开启区块链时代以来,近10年里,随着技术与生态的发展,基于区块链的分布式应用(dapp)呈现出井喷的趋势,而支撑着dapp的底层技术就是“区块...

    区块链大本营
  • 关于区块链安全的实际性思考

    区块链(Blockchain)是比特币的一个重要概念,它本质上是一个去中心化的数据库,同时作为比特币的底层技术。区块链是一串使用密码学方法相关联产生的数据块,每...

    周俊辉
  • 超级智能的形式和战略

    在人类的历史上,大约12万年以前,从非洲走出的尼安德特人遍及了欧洲大陆的所有角落,如果历史上不出意外,尼安德特人将会不断发展壮大,智力会不断提高,最终发展为高级...

    iOSDevLog
  • 本体技术视点 | 智能合约安全与漏洞分析(一)

    智能合约安全问题一直是区块链技术体系中探讨得比较多的话题之一。无论是以以太坊 EVM 虚拟机为代表的智能合约体系,还是以 EOS WASM 虚拟机为代表的智能合...

    本体Ontology
  • 区块链技术开发公司谈智能合约的优势与劣势

      智能合约概念可以追溯到1995年,是由一个计算机科学家尼克提出的,表示一个智能合约是一套以数字形式定义的承诺,合约参与方可以在上面执行这些承诺的协议。  

    YY谈网络那些事
  • 教AI打星际2也不难,试试暴雪和DeepMind的工具包 | 附论文+代码

    安妮 编译整理 量子位 出品 | 公众号 QbitAI ? 去年年底,DeepMind宣布想教会AI智能体玩《星际争霸2》(后简称星际2),计划创造出能击败人类...

    量子位
  • 区块链技术开发公司谈智能合约的作用

      区块链技术的出现到现在,已经接近10年了。区块链本质上是一个分布式数据库,伴随其诞生的数字货币比特币也成为炙手可热的高价值数字资产。从一开始的数字货币,发展...

    YY谈网络那些事

扫码关注云+社区

领取腾讯云代金券