SpringBoot - 收录java

放弃fastjson,拥抱Jackson

2020-06-22  本文已影响0人  大数据技术与应用实战

背景

最近由于阿里的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类型,目前支持以下的格式:


    @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

欢迎关注我的公众号,【大数据技术与应用实战】,获取更多精彩内容

上一篇下一篇

猜你喜欢

热点阅读