Fastjson妙用之@JSONField註解

北漂程式設計師發表於2021-11-16

在開發的過程中使用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方法上,分別影響反序列化、序列化過程;

 

有不正指出,歡迎指正!

 

相關文章