https://github.com/eishay/jvm-serializers/wiki
TypeReference
1. 基礎使用
在fastjson中提供了一個用於處理泛型反序列化的類TypeReference。
import com.alibaba.fastjson.TypeReference; List<VO> list = JSON.parseObject("...", new TypeReference<List<VO>>() {});
如下寫法有更好的性能
import com.alibaba.fastjson.TypeReference; final static Type type = new TypeReference<List<VO>>() {}.getType(); List<VO> list = JSON.parseObject("...", type);
在這里例子中,通過TypeReference能夠解決List中T的類型問題。
@Test public void TestListGenerics() { List<UserDO> userDOList = Arrays.asList(new UserDO(1L, "Name1"), new UserDO(2L, "Name2")); String userListStr = JSON.toJSONString(userDOList); List<UserDO> userDOS = JSON.parseArray(userListStr, UserDO.class); assertThat(userDOS.size()).isEqualTo(userDOList.size()); assertThat(userDOS.get(0)).isEqualToComparingFieldByField(userDOList.get(0)); assertThat(userDOS.get(1)).isEqualToComparingFieldByField(userDOList.get(1)); System.out.println(userDOS); List<UserDO> result = JSON.parseObject(userListStr, new TypeReference<List<UserDO>>() { }.getType()); assertThat(result.size()).isEqualTo(userDOList.size()); assertThat(result.get(0)).isEqualToComparingFieldByField(userDOList.get(0)); assertThat(result.get(1)).isEqualToComparingFieldByField(userDOList.get(1)); System.out.println(result); }
2. 帶參數使用
在1.2.9 & 1.1.49.android版本中,TypeReference支持泛型參數,方便一些框架實現通用的反序列化類。用法如下:
2.1. 單參數例子
public class Response<T> { public T data; } public static <T> Response<T> parseToMap(String json, Class<T> type) { return JSON.parseObject(json, new TypeReference<Response<T>>(type) {}); }
2.2. 雙參數例子
public static <K, V> Map<K, V> parseToMap(String json, Class<K> keyType, Class<V> valueType) { return JSON.parseObject(json, new TypeReference<Map<K, V>>(keyType, valueType) { }); } // 可以這樣使用 String json = "{1:{name:\"ddd\"},2:{name:\"zzz\"}}"; Map<Integer, Model> map = parseToMap(json, Integer.class, Model.class); assertEquals("ddd", map.get(1).name); assertEquals("zzz", map.get(2).name);
https://github.com/alibaba/fastjson/wiki/TypeReference
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.TypeReference; import com.google.gson.Gson; import com.google.gson.JsonSyntaxException; import com.google.gson.reflect.TypeToken; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.junit.Test; import java.lang.reflect.Type; /** * @Auther: cheng.tang * @Date: 2019/7/31 * @Description: */ public class GsonTest { private static final String source = "{\"code\":500,\"data\":\"\",\"msg\":\"未知異常\",\"success\":false}"; /** * com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 21 path $.data * <p> * at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:226) * at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:131) * at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:222) * at com.google.gson.Gson.fromJson(Gson.java:922) * at com.google.gson.Gson.fromJson(Gson.java:887) * at com.google.gson.Gson.fromJson(Gson.java:836) * at com.zkh360.gbb.user.utils.GsonTest.gsonDeserializationTest(GsonTest.java:36) * at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) * at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) * at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) * at java.lang.reflect.Method.invoke(Method.java:498) * at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) * at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) * at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) * at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) * at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) * at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) * at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) * at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) * at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) * at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) * at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) * at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) * at org.junit.runners.ParentRunner.run(ParentRunner.java:363) * at org.junit.runner.JUnitCore.run(JUnitCore.java:137) * at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68) * at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47) * at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242) * at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70) * Caused by: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 21 path $.data * at com.google.gson.stream.JsonReader.beginObject(JsonReader.java:385) * at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:215) * ... 28 more */ @Test(expected = JsonSyntaxException.class) public void gsonDeserializationTest() { Gson gson = new Gson(); Type type = new TypeToken<ResultDTO<UserIdDTO>>() { }.getType(); ResultDTO<UserIdDTO> resultDTO = gson.fromJson(source, type); System.out.println(JSON.toJSONString(resultDTO)); } @Test public void fastjsonDeserializationTest() { ResultDTO<UserIdDTO> userIdDTOResultDTO = JSON.parseObject(source, new TypeReference<ResultDTO<UserIdDTO>>() { }); System.out.println(JSON.toJSONString(userIdDTOResultDTO)); } }
fastjson實例化對象時,如果1,true 會轉換成true,其它的都為false
import com.alibaba.fastjson.JSON; import lombok.Data; import org.junit.Test; import static org.assertj.core.api.Java6Assertions.assertThat; /** * @author: tangcheng * @description: * @since: Created in 2018/08/03 16:31 */ public class JSONBooleanTypeTest { @Test public void testFastJson() { BooleanType booleanType = new BooleanType(); booleanType.setEnable(true); String output = JSON.toJSONString(booleanType); assertThat(output).isEqualTo("{\"enable\":true}"); /** * 字符串的值除了1和true外,都是false */ BooleanType serialObj = JSON.parseObject("{\"enable\":true}", BooleanType.class); assertThat(serialObj.getEnable()).isTrue(); serialObj = JSON.parseObject("{\"enable\":1}", BooleanType.class); assertThat(serialObj.getEnable()).isTrue(); serialObj = JSON.parseObject("{\"enable\":false}", BooleanType.class); assertThat(serialObj.getEnable()).isFalse(); serialObj = JSON.parseObject("{\"enable\":2}", BooleanType.class); assertThat(serialObj.getEnable()).isFalse(); serialObj = JSON.parseObject("{\"enable\":0}", BooleanType.class); assertThat(serialObj.getEnable()).isFalse(); serialObj = JSON.parseObject("{\"enable\":-1}", BooleanType.class); assertThat(serialObj.getEnable()).isFalse(); } @Data public static class BooleanType { private Boolean enable; } }
JSONObject.toJSONString(Object object, SerializerFeature... features)
SerializerFeature有用的一些枚舉值
QuoteFieldNames———-輸出key時是否使用雙引號,默認為true
WriteMapNullValue——–是否輸出值為null的字段,默認為false
WriteNullNumberAsZero—-數值字段如果為null,輸出為0,而非null
WriteNullListAsEmpty—–List字段如果為null,輸出為[],而非null
WriteNullStringAsEmpty—字符類型字段如果為null,輸出為”“,而非null
WriteNullBooleanAsFalse–Boolean字段如果為null,輸出為false,而非null
SerializerFeature.DisableCircularReferenceDetect ,
如果沒有設置這個參數會出現的問題【
FastJson如何解決循環引用/重復引用
fastjson支持循環引用/重復引用,並且是缺省打開的。
* 第一個例子序列化后輸出結果為:{"1":{},"2":{"$ref":"$.1"}}
第一個對象正常序列化,第二個對象則用引用表示
* 第二個列子序列化后輸出結果為:{"1":{"1":{"$ref":".."}}}
】:
如果對象中兩個字段存放的是相同的List 對象,則會出現這種情況
http://www.cnblogs.com/softidea/p/5873277.html
https://blog.csdn.net/qq_35873847/article/details/78850528
代碼:
List<JobResVO> jobs = recommendJobBO.getJobs();
resultResVO.setModern(jobs);
resultResVO.setTraditional(jobs);
Converter中FastJson的配置:
@Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { FastJsonHttpMessageConverter httpMessageConverter = new FastJsonHttpMessageConverter(); FastJsonConfig fastJsonConfig = new FastJsonConfig(); fastJsonConfig.setSerializerFeatures(SerializerFeature.QuoteFieldNames, SerializerFeature.WriteEnumUsingToString, SerializerFeature.WriteMapNullValue, SerializerFeature.WriteDateUseDateFormat); fastJsonConfig.setSerializeFilters((ValueFilter) (o, s, source) -> { if (source == null) { return ""; } if (source instanceof Date) { return ((Date) source).getTime(); } return source; }); httpMessageConverter.setFastJsonConfig(fastJsonConfig); converters.add(httpMessageConverter); }
解決辦法:
@Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { FastJsonHttpMessageConverter httpMessageConverter = new FastJsonHttpMessageConverter(); FastJsonConfig fastJsonConfig = new FastJsonConfig(); fastJsonConfig.setSerializerFeatures(SerializerFeature.QuoteFieldNames, SerializerFeature.WriteEnumUsingToString, SerializerFeature.WriteMapNullValue, SerializerFeature.WriteDateUseDateFormat, SerializerFeature.DisableCircularReferenceDetect); fastJsonConfig.setSerializeFilters((ValueFilter) (o, s, source) -> { if (source == null) { return ""; } if (source instanceof Date) { return ((Date) source).getTime(); } return source; }); httpMessageConverter.setFastJsonConfig(fastJsonConfig); converters.add(httpMessageConverter); }
上面的SerializerFeature主要是針對Object對象序列化轉換時的情況(這個時候才能判斷參數的類型),而在Map中,你放進入了null就是null,進行序列化時已經沒法判斷它原來的類型了,所以並沒有起作用。要使用SerializerFeature里相關null的參數,應該傳入對象進行序列化。
對規則的理解:
-
SerializerFeature.WriteMapNullValue 是否輸出值為null的字段,默認為false也就是說有null時會輸出而不是忽略(默認策略是忽略,所以看不到為null的字段)
-
WriteNullStringAsEmpty—字符類型字段如果為null,輸出為”“,而非null
注意是字段是字段是字段,而不是json.put("key",null),所以用它時,字段為null的可以轉換為空字符串。 -
如果讓輸出的json中所有為null的字符串都變成空字符串,最簡單的做法就是加一個值過濾器,這樣就避免了有的字段為null,有的字段為空字符的現象。
示例代碼
import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.serializer.SerializerFeature; import com.alibaba.fastjson.serializer.ValueFilter; public class Demo1 { public class Student { private String name; private int age; private boolean isMale; private Student gf; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public boolean isMale() { return isMale; } public void setMale(boolean isMale) { this.isMale = isMale; } public Student getGf() { return gf; } public void setGf(Student gf) { this.gf = gf; } } private static ValueFilter filter = new ValueFilter() { @Override public Object process(Object obj, String s, Object v) { if (v == null) return ""; return v; } }; public static void main(String[] args) { new Demo1().foo(); new Demo1().bar(); } private void foo() { System.out.println("foo()---------------------------"); JSONObject j1 = new JSONObject(); j1.put("name", "zhangsan"); j1.put("age", 13); j1.put("isMale", true); j1.put("gf", null); Map<String, Object> fav = new HashMap<String, Object>(); Set<String> books = new HashSet<String>(); books.add("三國"); books.add("史記"); fav.put("history", books); String[] arts = new String[] {}; fav.put("arts", arts); String[] musics = new String[] { "北京歡迎你", "畫心" }; fav.put("musics", musics); List<String> sports = new ArrayList<String>(); fav.put("sports", sports); j1.put("fav", fav); List<Student> classmates = new ArrayList<Student>(); classmates.add(new Student()); Student lisi = new Student(); lisi.setMale(false); lisi.setAge(11); classmates.add(lisi); Student zhangsan = new Student(); zhangsan.setAge(13); zhangsan.setName("張三"); zhangsan.setMale(true); zhangsan.setGf(lisi); classmates.add(zhangsan); j1.put("classmates", classmates); String str = null; j1.put("str", str); System.out.println(j1.toString()); System.out .println(JSON.toJSONString(j1, SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullStringAsEmpty)); System.out.println( JSON.toJSONString(j1, filter, SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullStringAsEmpty)); System.out.println(JSON.toJSONString(j1, SerializerFeature.WriteNullStringAsEmpty)); System.out.println(JSON.toJSONString(j1, filter, SerializerFeature.WriteNullStringAsEmpty)); Map<String, JSONObject> m = new HashMap<String, JSONObject>(); m.put("key", j1); System.out.println( JSON.toJSONString(m, SerializerFeature.WriteNonStringKeyAsString, SerializerFeature.WriteNullStringAsEmpty)); System.out.println(JSON.toJSONString(m, filter, SerializerFeature.WriteNonStringKeyAsString, SerializerFeature.WriteNullStringAsEmpty)); } private void bar() { System.out.println("bar()---------------------------"); Student zhangsan = new Student(); zhangsan.setAge(13); zhangsan.setName("張三"); zhangsan.setMale(true); Student lisi = new Student(); // lisi.setName("lisi"); lisi.setMale(false); lisi.setAge(11); zhangsan.setGf(lisi); System.out.println( JSON.toJSONString(zhangsan, SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullStringAsEmpty)); System.out.println(JSON.toJSONString(zhangsan, SerializerFeature.WriteMapNullValue)); System.out.println(JSON.toJSONString(zhangsan, SerializerFeature.WriteNullStringAsEmpty)); System.out.println(JSON.toJSONString(zhangsan)); System.out.println(JSON.toJSONString(zhangsan, filter)); System.out.println(JSON.toJSONString(zhangsan, filter, SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNullStringAsEmpty)); } }
foo()--------------------------- {"isMale":true,"name":"zhangsan","classmates":[{"age":0,"male":false},{"age":11,"male":false},{"age":13,"gf":{"$ref":"$.classmates[1]"},"male":true,"name":"張三"}],"fav":{"sports":[],"musics":["北京歡迎你","畫心"],"history":["史記","三國"],"arts":[]},"age":13} {"str":null,"isMale":true,"name":"zhangsan","classmates":[{"age":0,"gf":null,"male":false,"name":""},{"age":11,"gf":null,"male":false,"name":""},{"age":13,"gf":{"$ref":"$.classmates[1]"},"male":true,"name":"張三"}],"fav":{"sports":[],"musics":["北京歡迎你","畫心"],"history":["史記","三國"],"arts":[]},"age":13,"gf":null} {"str":"","isMale":true,"name":"zhangsan","classmates":[{"age":0,"gf":"","male":false,"name":""},{"age":11,"gf":"","male":false,"name":""},{"age":13,"gf":{"$ref":"$.classmates[1]"},"male":true,"name":"張三"}],"fav":{"sports":[],"musics":["北京歡迎你","畫心"],"history":["史記","三國"],"arts":[]},"age":13,"gf":""} {"isMale":true,"name":"zhangsan","classmates":[{"age":0,"male":false},{"age":11,"male":false},{"age":13,"gf":{"$ref":"$.classmates[1]"},"male":true,"name":"張三"}],"fav":{"sports":[],"musics":["北京歡迎你","畫心"],"history":["史記","三國"],"arts":[]},"age":13} {"str":"","isMale":true,"name":"zhangsan","classmates":[{"age":0,"gf":"","male":false,"name":""},{"age":11,"gf":"","male":false,"name":""},{"age":13,"gf":{"$ref":"$.classmates[1]"},"male":true,"name":"張三"}],"fav":{"sports":[],"musics":["北京歡迎你","畫心"],"history":["史記","三國"],"arts":[]},"age":13,"gf":""} {"key":{"isMale":true,"name":"zhangsan","classmates":[{"age":0,"male":false},{"age":11,"male":false},{"age":13,"gf":{"$ref":"$.key.classmates[1]"},"male":true,"name":"張三"}],"fav":{"sports":[],"musics":["北京歡迎你","畫心"],"history":["史記","三國"],"arts":[]},"age":13}} {"key":{"str":"","isMale":true,"name":"zhangsan","classmates":[{"age":0,"gf":"","male":false,"name":""},{"age":11,"gf":"","male":false,"name":""},{"age":13,"gf":{"$ref":"$.key.classmates[1]"},"male":true,"name":"張三"}],"fav":{"sports":[],"musics":["北京歡迎你","畫心"],"history":["史記","三國"],"arts":[]},"age":13,"gf":""}} bar()--------------------------- {"age":13,"gf":{"age":11,"gf":null,"male":false,"name":""},"male":true,"name":"張三"} {"age":13,"gf":{"age":11,"gf":null,"male":false,"name":null},"male":true,"name":"張三"} {"age":13,"gf":{"age":11,"male":false},"male":true,"name":"張三"} {"age":13,"gf":{"age":11,"male":false},"male":true,"name":"張三"} {"age":13,"gf":{"age":11,"gf":"","male":false,"name":""},"male":true,"name":"張三"} {"age":13,"gf":{"age":11,"gf":"","male":false,"name":""},"male":true,"name":"張三"}
JsonPathTestData.json
{ "store": { "book": [ { "category": "reference", "author": "Nigel Rees", "title": "Sayings of the Century", "price": 8.95 }, { "category": "fiction", "author": "Evelyn Waugh", "title": "Sword of Honour", "price": 12.99, "isbn": "0-553-21311-3" } ], "bicycle": { "color": "red", "price": 19.95 } } }
@Test public void testJsonPath() throws IOException { InputStream resourceAsStream = this.getClass().getResourceAsStream("/JsonPathTestData.json"); String jsonStr = IOUtils.toString(resourceAsStream, "utf-8"); System.out.println(jsonStr); System.out.println(jsonStr); JSONObject jsonObject = JSON.parseObject(jsonStr); System.out.println("\nBook數目:" + JSONPath.eval(jsonObject, "$.store.book.size()")); System.out.println("第一本書title:" + JSONPath.eval(jsonObject, "$.store.book[0].title")); System.out.println("price大於10元的book:" + JSONPath.eval(jsonObject, "$.store.book[price > 10]")); System.out.println("price大於10元的title:" + JSONPath.eval(jsonObject, "$.store.book[price > 10][0].title")); System.out.println("category(類別)為fiction(小說)的book:" + JSONPath.eval(jsonObject, "$.store.book[category = 'fiction']")); System.out.println("bicycle的所有屬性值" + JSONPath.eval(jsonObject, "$.store.bicycle.*")); System.out.println("bicycle的color和price屬性值" + JSONPath.eval(jsonObject, "$.store.bicycle['color','price']")); } @Test public void testGenerics() { Result<User> result = new Result<>(); result.setMsg("Success"); List<User> users = new ArrayList<>(); users.add(new User(1L, "Name1")); users.add(new User(2L, "Name2")); result.setModule(users); String js = JSON.toJSONString(result); System.out.println(js); //java.lang.ClassCastException: com.alibaba.fastjson.JSONObject cannot be cast to com.tangcheng.learning.json.User // Result<User> obj = (Result<User>) JSON.parseObject(js, Result.class); Result<User> userResult = JSON.parseObject(js, new TypeReference<Result<User>>() { }); System.out.println(userResult); }
public class User { private Long id; private String name; public User() { } public User(Long id, String name) { this.id = id; this.name = name; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + '}'; } }
import java.util.List; public class Result<T> { private String msg; private List<T> module; public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } public List<T> getModule() { return module; } public void setModule(List<T> module) { this.module = module; } @Override public String toString() { return "Result{" + "msg='" + msg + '\'' + ", module=" + module + '}'; } }
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.TypeReference; import com.alibaba.fastjson.util.ParameterizedTypeImpl; import lombok.Data; @Data public class Response<T> { private T data; @Override public String toString() { return JSON.toJSONString(this); } public static void main(String[] args) { String jsonText = "{\"data\":{\"id\":1,\"name\":\"張三\"}}"; Response<User> response = JSON.parseObject(jsonText, new ParameterizedTypeImpl(new Class[]{User.class}, null, Response.class)); /** * {"data":{"id":1,"name":"張三"}} */ System.out.println(response); response = JSON.parseObject(jsonText, new TypeReference<Response<User>>() { }); /** * {"data":{"id":1,"name":"張三"}} */ System.out.println(response); } } @Data class User { private Integer id; private String name; @Override public String toString() { return JSON.toJSONString(this); } }
https://www.slideshare.net/randfish/inside-googles-numbers-in-2017?next_slideshow=1
由於json中的key與bean中的屬性不能匹配,因此在轉換過程中出現了部分屬性為null的情況。經過查看官方文檔,發現可以使用@JSONField進行解釋,但是並沒有詳細的使用說明。
@JSONField的作用對象:
1. Field
2. Setter 和 Getter方法
注:FastJson在進行操作時,是根據getter和setter的方法進行的,並不是依據Field進行。
一、作用Field
@JSONField作用在Field時,其name不僅定義了輸入key的名稱,同時也定義了輸出的名稱。
二、作用在setter和getter方法上
顧名思義,當作用在setter方法上時,就相當於根據 name 到 json中尋找對應的值,並調用該setter對象賦值。
當作用在getter上時,在bean轉換為json時,其key值為name定義的值
在fastjson-1.2.12版本中,JSONField支持一個新的配置項jsonDirect,
它的用途是:當你有一個字段是字符串類型,里面是json格式數據,你希望直接輸入,而不是經過轉義之后再輸出。
Model:
import com.alibaba.fastjson.annotation.JSONField; public static class Model { public int id; @JSONField(jsonDirect=true) public String value; }
Usage:
Model model = new Model(); model.id = 1001; model.value = "{}"; String json = JSON.toJSONString(model); Assert.assertEquals("{\"id\":1001,\"value\":{}}", json);
https://github.com/alibaba/fastjson/wiki/JSONField_jsonDirect_cn
https://github.com/alibaba/fastjson/issues/1244
http://www.cnblogs.com/softidea/p/5681928.html
fastjson 過濾不需要的字段或者只要某些字段
//第一種:在對象響應字段前加注解,這樣生成的json也不包含該字段。 @JSONField(serialize=false) private String name;
第二種:在對象對應字段前面加transient,表示該字段不用序列化,即在生成json的時候就不會包含該字段了。 private transient String name;
transient使用小結 1)一旦變量被transient修飾,變量將不再是對象持久化的一部分,該變量內容在序列化后無法獲得訪問。 2)transient關鍵字只能修飾變量,而不能修飾方法和類。注意,本地變量是不能被transient關鍵字修飾的。變量如果是用戶自定義類變量,則該類需要實現Serializable接口。 3)被transient關鍵字修飾的變量不再能被序列化,一個靜態變量不管是否被transient修飾,均不能被序列化。 第三點可能有些人很迷惑,因為發現在User類中的username字段前加上static關鍵字后,程序運行結果依然不變,即static類型的username也讀出來為“Alexia”了,這不與第三點說的矛盾嗎?
實際上是這樣的:第三點確實沒錯(一個靜態變量不管是否被transient修飾,均不能被序列化),反序列化后類中static型變量username的值為當前JVM中對應static變量的值,這個值是JVM中的不是反序列化得出的
https://www.cnblogs.com/lanxuezaipiao/p/3369962.html
//第三種:使用fastjson的攔截器 PropertyFilter profilter = new PropertyFilter(){ @Override public boolean apply(Object object, String name, Object value) { if(name.equalsIgnoreCase("last")){ //false表示last字段將被排除在外 return false; } return true; } }; json = JSON.toJSONString(user, profilter); System.out.println(json);
https://blog.csdn.net/stubbornness1219/article/details/52947013
jackson也是一個很優秀的jackson庫,但是如果你因為某些理由想遷移到fastjson,這個指南將會為你介紹如何從jackson遷移到fastjson。
Annotions
在fastjson中,有四個Annotation,JSONType、JSONField、JSONCreator、JSONPOJOBuilder,能夠完成jackson大多數Annotation對應的功能。
1. JsonView遷移
在fastjson中,提供有一個LabelFilter,能夠實現Jackson JsonView的功能,用於定制序列化。詳細文檔 https://github.com/alibaba/fastjson/wiki/LabelFilter
2. JsonPOJOBuilder
在Jackson中提供了對Builder模式支持的JsonPOJOBuilder,在fastjson中對應的是JSONPOJOBuilder。詳細文檔 https://github.com/alibaba/fastjson/wiki/BuilderSupport
3. JsonAnyGetter & JsonAnySetter & JsonUnwrapped
在fastjson 1.2.32版本中引入JSONField.unwrapped配置,支持類似JsonAnyGetter/JsonAnySetter的功能,詳細文檔 https://github.com/alibaba/fastjson/wiki/JSONField_unwrapped_cn
4. JsonPropertyOrder
在fastjson的JSONType.orders提供了同樣的功能。例如:
@JSONType(orders={"name", "id"}) public static class VO { public int id; public String name; }
5. JsonRawValue
在fastjson中,通過JSONField.jsonDirect配置能實現同樣的功能。
public static class Model { public int id; @JSONField(jsonDirect=true) public String value; }
6. JsonSerialize
在fastjson中,可以通過使用JSONField.serializeUsing和JSONType.serializer實現同樣的功能。
7. JsonCreator
在fastjson中有對應的JSONCreator
8. JsonSetter
在fastjson中,可以用JSONField實現同樣的功能。
9. JsonDeserialize
在fastjson中,可以通過使用JSONField.deserializeUsing和JSONType.deserializer實現同樣的功能。
10. JsonIgnoreProperties
在fastjson中,可以通過使用JSONType.ignores實現同樣的功能
11. JsonIgnore
在fastjson中,可以通過使用JSONField.serilaize=false和JSONField.deserilaize=false和實現同樣的功能
12. JsonFormat
在fastjson中,可以通過使用JSONField.format實現同樣的功能
13. Jackson Polymorphic Type Handling Annotations
在fastjson中,可以通過JSONType.seeAlso實現類似的功能。詳細文檔 https://github.com/alibaba/fastjson/wiki/JSONType_seeAlso_cn
https://github.com/alibaba/fastjson/wiki/guid_to_migrating_from_jackson_to_fastjson_cn
2.4. @JsonRawValue
@JsonRawValue is used to instruct the Jackson to serialize a property exactly as is.
In the following example – we use @JsonRawValue to embed some custom JSON as a value of an entity:
1
2
3
4
5
6
|
public
class
RawBean {
public
String name;
@JsonRawValue
public
String json;
}
|
The output of serializing the entity is:
1
2
3
4
5
6
|
{
"name"
:
"My bean"
,
"json"
:{
"attr"
:
false
}
}
|
And a simple test:
1
2
3
4
5
6
7
8
9
10
|
@Test
public
void
whenSerializingUsingJsonRawValue_thenCorrect()
throws
JsonProcessingException {
RawBean bean =
new
RawBean(
"My bean"
,
"{"
attr
":false}"
);
String result =
new
ObjectMapper().writeValueAsString(bean);
assertThat(result, containsString(
"My bean"
));
assertThat(result, containsString(
"{"
attr
":false}"
));
}
|
http://www.baeldung.com/jackson-annotations
9.4 日期格式處理
Fastjson能識別下面這么多種日期格式的字符串:
1 |
private final static String defaultPatttern = "yyyy-MM-dd HH:mm:ss"; |
默認序列化Date輸出使用”yyyy-MM-dd HH:mm:ss”格式,可以用UseISO8601DateFormat特性換成”yyyy-MM-dd’T’HH:mm:ss”格式。
1 |
JSON.defaultTimeZone = TimeZone.getTimeZone("Asia/Shanghai"); |
9.5 常見序列化特性的使用
Fastjson的序列化特性定義在枚舉類com\alibaba\fastjson\serializer\SerializerFeature.java中,目前正好有30項。
可以通過設置多個特性到FastjsonConfig中全局使用,也可以在某個具體的JSON.writeJSONString時作為參數使用。
- QuoteFieldNames, //key使用引號
- UseSingleQuotes, //使用單引號
- WriteMapNullValue, //輸出Map的null值
- WriteEnumUsingToString, //枚舉屬性輸出toString的結果
- WriteEnumUsingName, //枚舉數據輸出name
- UseISO8601DateFormat, //使用日期格式
- WriteNullListAsEmpty, //List為空則輸出[]
- WriteNullStringAsEmpty, //String為空則輸出””
- WriteNullNumberAsZero, //Number類型為空則輸出0
- WriteNullBooleanAsFalse, //Boolean類型為空則輸出false
- SkipTransientField,
- SortField, //排序字段
- WriteTabAsSpecial,
- PrettyFormat, // 格式化JSON縮進
- WriteClassName, // 輸出類名
- DisableCircularReferenceDetect, // 禁止循環引用
- WriteSlashAsSpecial, // 對斜杠’/’進行轉義
- BrowserCompatible,
- WriteDateUseDateFormat, // 全局修改日期格式,默認為false。JSON.DEFFAULT_DATE_FORMAT = “yyyy-MM-dd”;JSON.toJSONString(obj, SerializerFeature.WriteDateUseDateFormat);
- NotWriteRootClassName,
- DisableCheckSpecialChar,
- BeanToArray,
- WriteNonStringKeyAsString,
- NotWriteDefaultValue,
- BrowserSecure,
- IgnoreNonFieldGetter,
- WriteNonStringValueAsString,
- IgnoreErrorGetter,
- WriteBigDecimalAsPlain,
- MapSortField
使用示例如下(可以參見此處):
1 |
Word word = new Word(); |
9.6 Annotation注解的使用
1) JSONField
可以配置在屬性(setter、getter)和字段(必須是public field)上。
詳情參見此處:JSONField用法
1 |
package com.alibaba.fastjson.annotation; |
1 |
|
http://kimmking.github.io/2017/06/06/json-best-practice/
7. fastjson序列化的需要像json-lib一樣配置java bean的序列化么?
不需要,fastjson的序列化和反序列化都不需要做特別配置,唯一的要求是,你序列化的類符合java bean規范。
8. fastjson如何處理日期
fastjson處理日期的API很簡單,例如:
JSON.toJSONStringWithDateFormat(date, "yyyy-MM-dd HH:mm:ss.SSS")
使用ISO-8601日期格式
JSON.toJSONString(obj, SerializerFeature.UseISO8601DateFormat);
全局修改日期格式
JSON.DEFFAULT_DATE_FORMAT = "yyyy-MM-dd"; JSON.toJSONString(obj, SerializerFeature.WriteDateUseDateFormat);
反序列化能夠自動識別如下日期格式:
- ISO-8601日期格式
- yyyy-MM-dd
- yyyy-MM-dd HH:mm:ss
- yyyy-MM-dd HH:mm:ss.SSS
- 毫秒數字
- 毫秒數字字符串
- .NET JSON日期格式
- new Date(198293238)
11. IE 6不支持JSON帶中文字符串,要怎么處理?
fastjson提供了BrowserCompatible這個配置,打開之后,所有的中文都會序列化為\uXXXX這種格式,字節數會多一些,但是能兼容IE 6。
String jsonString = JSON.toJSONString(obj, SerializerFeature.BrowserCompatible);
10. 當對象存在引用時,序列化后的結果瀏覽器不支持,怎么辦?
使用SerializerFeature.DisableCircularReferenceDetect特性關閉引用檢測和生成。
例如:
String jsonString = JSON.toJSONString(obj, SerializerFeature.DisableCircularReferenceDetect);
https://github.com/alibaba/fastjson/wiki/%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98
做個分析 FastJson
在使用 toJSONString
會使用 寫入操作,而 我的類里面有這樣一個方法 public int getLengthOfByte()
這樣FastJson
就會認為 這個類 有一個 lengthOfByte
的屬性,於是就出現了異常,解決方法
@JSONType(ignores = "lengthOfByte") public class DRMessageBody { public int getLengthOfByte(){ String json = toJson(); int num = -1; num = json.getBytes().length; if(num==-1){ new RuntimeException("Messagebody of json length is error!"); } return num; } }
https://www.jianshu.com/p/f96e257c7682