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