在開發的過程中使用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方法上,分別影響反序列化、序列化過程;
有不正指出,歡迎指正!