• Fastjson妙用之@JSONField注解


    在开发的过程中使用json格式的地方非常多,现在前后端分离的项目中,前后端数据交换的格式一般为json,这种格式的优/缺点这里不再赘述,感兴趣的可以百度。把java中的实体类序列化为json的方式也有很多方式,今天来看看常用到的fastjson。

    都知道fastjson是阿里开源的一个序列化/反序列化的jar包,在日常的开发过程中经常会碰到,也是使用频率较高的一款工具。

    这里要了解一个概念,那就是序列化/反序列化,序列化是把一个java对象转化为其他的形式,如json、XML、对象字节;反序列化则是把json、XML、对象字节转化为java对象。

    一、初始Fastjson

    1、环境搭建

    要想使用fastjson,首先需要引入fastjson的包,我这里使用的是maven工具,所以这里只要在pom文件中添加相应的依赖即可,

    <!--fastjson-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.78</version>
        </dependency>

    2、一个小例子

    有一个实体类,

    package com.atssg.test;
    
    
    import lombok.Data;
    
    @Data
    public class Student {
        private Integer id;
        private String name;
        private String address;
        private String phoneNumber;
    
    }

    下面看测试方法

    package com.atssg.test;
    
    import com.alibaba.fastjson.JSON;
    import lombok.extern.slf4j.Slf4j;
    
    @Slf4j
    public class TestFastJson {
        public static void main(String[] args) {
            Student student=new Student();
            student.setId(1);
            student.setName("tom");
            student.setAddress("beijing");
            student.setPhoneNumber("010-6668899");
    
            //把对象转化为json串
            String jsonString=JSON.toJSONString(student);
            log.info("student序列化为:{}",jsonString);
        }
    }

    下面看测试结果

    22:22:41.657 [main] INFO com.atssg.test.TestFastJson - student序列化为:{"address":"beijing","id":1,"name":"tom","phoneNumber":"010-6668899"}
    
    Process finished with exit code 0

    从上面可以看到打印除了序列化为json的字符串,这里是一个序列化的过程,当然也可以把一个字符串反序列化为java对象。

    二、@JSONField注解

    在上面的例子中,student被序列化为一个json字符串,字符串是键值对的形式,键是Student的属性名。

    现在有这样的一个需求,要返回给前端Student的json字符串,但不想给前端phoneNumber字段,你要怎么做那?一个比较容易想到的方式是从字符串中把这个属性去掉,或者重新生成一个不包含phoneNumber的实体对象。难道没有更好的方式么

    在fastjson提供了@JSONField这样一个注解。

    1、@JSONField(serialize = false)

    @JSONField注解中有seaialize这样一个属性,看名称应该和序列化有关,尝试下看看效果,

    package com.atssg.test;
    
    
    import com.alibaba.fastjson.annotation.JSONField;
    import lombok.Data;
    
    @Data
    public class Student {
        private Integer id;
        private String name;
        private String address;
        @JSONField(serialize = false)
        private String phoneNumber;
    
    }

    再看上面的测试类的执行结果,

    22:30:26.678 [main] INFO com.atssg.test.TestFastJson - student序列化为:{"address":"beijing","id":1,"name":"tom"}
    
    Process finished with exit code 0

    可以看到轻轻松松phoneNumber不见了,也就是说@JSONField(serialize=false)起作用了,该属性不会参与序列化,反之,不加该注解或serialize的值设为true,则会参与序列化。

     2、@JSONField(name= "XXX")

    在和前端的交互过程中,可能存在这样的情况,java类中定义的字段的形式为驼峰,但前端需要的是以_连接的形式,要怎么做那,在@JSONField中有name属性,

    package com.atssg.test;
    
    
    import com.alibaba.fastjson.annotation.JSONField;
    import lombok.Data;
    
    @Data
    public class Student {
        private Integer id;
        private String name;
        private String address;
        @JSONField(name = "phone_number")
        private String phoneNumber;
    
    }

    在phoneNuber上注解@JSONField且name为phone_number,看测试结果,

    21:47:48.766 [main] INFO com.atssg.test.TestFastJson - student序列化为:{"address":"beijing","id":1,"name":"tom","phone_number":"010-6668899"}

    可以看到在序列化的json字符串中出现了phone_number,说明@JSONField起了作用,在序列化的时候指定序列化字段的名称,如果指定了使用指定的(@JSONField中name的值),如果不指定使用java类中属性的名字。

    3、@JSONField注解

    在上面,我们看了@JSONField的两种用法,还有很多用法,这里不一一列举,看下@JSONField这个注解的定义,

    //
    // Source code recreated from a .class file by IntelliJ IDEA
    // (powered by FernFlower decompiler)
    //
    
    package com.alibaba.fastjson.annotation;
    
    import com.alibaba.fastjson.parser.Feature;
    import com.alibaba.fastjson.serializer.SerializerFeature;
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
    public @interface JSONField {
        int ordinal() default 0;
    
        String name() default "";
    
        String format() default "";
    
        boolean serialize() default true;
    
        boolean deserialize() default true;
    
        SerializerFeature[] serialzeFeatures() default {};
    
        Feature[] parseFeatures() default {};
    
        String label() default "";
    
        boolean jsonDirect() default false;
    
        Class<?> serializeUsing() default Void.class;
    
        Class<?> deserializeUsing() default Void.class;
    
        String[] alternateNames() default {};
    
        boolean unwrapped() default false;
    
        String defaultValue() default "";
    }

    在这个注解上使用了@Target注解标注,@Target中的值为{ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER},也就是说@JSONField可以标注在方法上、字段、参数上。在上面的例子中,我们把@JSONField用在了字段上,下面看使用在方法上的例子,在一个类中有getXXX/setXXX方法,看@JSONField用在getXXX/setXXX的用法。

    package com.atssg.test;
    
    
    import com.alibaba.fastjson.annotation.JSONField;
    import lombok.Data;
    
    @Data
    public class Student {
        private Integer id;
        private String name;
        private String address;
    
        private String phoneNumber;
    
        //getXXX方法用在序列化过程中
        @JSONField(serialize = false)
        public String getPhoneNumber() {
            return phoneNumber;
        }
    
        //setXXX方法用在反序列化过程中
        @JSONField(deserialize = false)
        public void setPhoneNumber(String phoneNumber) {
            this.phoneNumber = phoneNumber;
        }
    }

    看测试结果

    21:59:28.334 [main] INFO com.atssg.test.TestFastJson - student序列化为:{"address":"beijing","id":1,"name":"tom"}

    再来看反序列化的测试结果,测试类,

    package com.atssg.test;
    
    import com.alibaba.fastjson.JSON;
    import lombok.extern.slf4j.Slf4j;
    
    @Slf4j
    public class TestFastJson {
        public static void main(String[] args) {
            Student student=new Student();
            student.setId(1);
            student.setName("tom");
            student.setAddress("beijing");
            student.setPhoneNumber("010-6668899");
    
            //把对象转化为json串
            String jsonString=JSON.toJSONString(student);
            log.info("student序列化为:{}",jsonString);
            //反序列化
            String str="{\"address\":\"beijing\",\"id\":1,\"name\":\"tom\",\"phoneNumber\":\"010-6668899\"}";
            Student stu=JSON.parseObject(str,Student.class);
            log.info("反序列化的结果:{}",stu);
    
        }
    }

    使用了含有phoneNumber的字符串,看反序列化的结果,

    22:04:04.746 [main] INFO com.atssg.test.TestFastJson - student序列化为:{"address":"beijing","id":1,"name":"tom"}
    22:04:04.776 [main] INFO com.atssg.test.TestFastJson - 反序列化的结果:Student(id=1, name=tom, address=beijing, phoneNumber=null)

    可以看到phoneNumber的值为null,证明该属性未取得反序列化的值,证明了@JSONField用在setXXX方法上起到了反序列化的控制作用。

    三、总结

    本文分享了fastjson中@JSONField的用法,主要是在序列化/反序列化的过程中,主要体现在以下几个方面,

    1、@JSONField用在字段上影响序列化/反序列化两个过程;

    2、@JSONField用在setXXX、getXXX方法上,分别影响反序列化、序列化过程;

    有不正指出,欢迎指正!

     

    一个爱写文章的程序员,欢迎关注我的公众号“北漂程序员”。我有故事,你有酒吗
  • 相关阅读:
    SQL SERVER中变量的定义、赋值与使用
    框架设计总结
    Sass学习之路(5)——变量
    gulp入坑系列(4)——gulp的代码转换
    gulp入坑系列(3)——创建多个gulp.task
    Sass学习之路(4)——不同样式风格的输出方式
    Sass学习之路(3)——Sass编译
    gulp入坑系列(2)——初试JS代码合并与压缩
    gulp入坑系列(1)——安装gulp
    Sass学习之路(2)——Sass环境安装(windows版)
  • 原文地址:https://www.cnblogs.com/teach/p/15431163.html
Copyright © 2020-2023  润新知