Gson中@JsonAdater注解的幾種方式總結(jié)
Gson @JsonAdater注解的幾種方式
總結(jié)
可以通過自定義TypeAdapter和TypeAdapterFactory的方式,自定義gson的序列化和反序列規(guī)則,TypeAdapterFactory可以拿到上下文gson、TokenType類型;
也可以通過繼承JsonReader重新寫一次代碼,在beginArray和endArray想辦法跳過array的string形式的左右 雙引號(hào)", gson.fromJson(myJsonReader, Type)也可以實(shí)現(xiàn) 解析時(shí)自動(dòng)將String變?yōu)長(zhǎng)ist,但采用注解@JsonAdapter的方式更為正規(guī)一些;
問題描述
json字符串:
{ ? ? "cityIds": "[1,2,1001,13131]", ? ? "types": "[{\"name\": \"biz\",\"details\": [1]}]" }
java對(duì)象定義:
?@Data ? ? public static class RequestParams { ? ? ? ?// json字符串里對(duì)應(yīng)的是String ? ? ? ? private List<TypeItem> types; ? ? ? ? private List<Integer> cityIds; ? ? } ? ? @Data ? ? public static class TypeItem { ? ? ? ? private String name; ? ? ? ? private List<Integer> details; ? ? }
可以看到j(luò)son里面cityIds和types都是String,而pojo里則是List,使用gson的fromJson將json轉(zhuǎn)為pojo會(huì)發(fā)生報(bào)錯(cuò)
方式一
? @JsonAdapter(StringCollectionTypeAdapterFactory.class) ? ? ?private List<TagItem> tags; ? ? ?@JsonAdapter(StringCollectionTypeAdapterFactory.class) ? ? ?private List<Integer> cityIds; public static class StringCollectionTypeAdapterFactory implements TypeAdapterFactory { ? ? ? ? @Override ? ? ? ? public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) { ? ? ? ? ? ? // 為了write的時(shí)候能使用到elementTypeAdapter ? ? ? ? ? ? Type type = typeToken.getType(); ? ? ? ? ? ? Class<? super T> rawType = typeToken.getRawType(); ? ? ? ? ? ? if (!Collection.class.isAssignableFrom(rawType)) { ? ? ? ? ? ? ? ? return null; ? ? ? ? ? ? } ? ? ? ? ? ? Type elementType = $Gson$Types.getCollectionElementType(type, rawType); ? ? ? ? ? ? TypeAdapter<?> elementTypeAdapter = gson.getAdapter(TypeToken.get(elementType)); ? ? ? ? ? ?? ? ? ? ? ? ? TypeAdapter<T> result = new Adapter(gson, elementTypeAdapter, typeToken); ? ? ? ? ? ? return result; ? ? ? ? } ? ? ? ? private static final class Adapter<E> extends TypeAdapter<Collection<E>> { ? ? ? ? ? ? private final TypeAdapter<E> elementTypeAdapter; ? ? ? ? ? ? private final Gson gson; ? ? ? ? ? ? private final TypeToken listType; ? ? ? ? ? ? public Adapter(Gson context, TypeAdapter<E> elementTypeAdapter, TypeToken listType) { ? ? ? ? ? ? ? ? this.elementTypeAdapter = elementTypeAdapter; ? ? ? ? ? ? ? ? this.gson = context; ? ? ? ? ? ? ? ? this.listType = listType; ? ? ? ? ? ? } ? ? ? ? ? ? @Override public Collection<E> read(JsonReader in) throws IOException { ? ? ? ? ? ? ? ? if (in.peek() == JsonToken.NULL) { ? ? ? ? ? ? ? ? ? ? in.nextNull(); ? ? ? ? ? ? ? ? ? ? return null; ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? List<E> list = gson.fromJson(in.nextString(), listType.getType()); ? ? ? ? ? ? ? ? return list; ? ? ? ? ? ? } ? ? ? ? ? ? ? // write后可以將array的string格式,重新變成array ? ? ? ? ? ? @Override public void write(JsonWriter out, Collection<E> collection) throws IOException { ? ? ? ? ? ? ? ? if (collection == null) { ? ? ? ? ? ? ? ? ? ? out.nullValue(); ? ? ? ? ? ? ? ? ? ? return; ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? out.beginArray(); ? ? ? ? ? ? ? ? for (E element : collection) { ? ? ? ? ? ? ? ? ? ? elementTypeAdapter.write(out, element); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? out.endArray(); ? ? ? ? ? ? } ? ? ? ? } ? ? }
方式二-write原樣
public static class StringCollectionTypeAdapterFactory1 implements TypeAdapterFactory { ? ? ? ? @Override ? ? ? ? public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) { ? ? ? ? ? ? return new Adapter(gson, typeToken); ? ? ? ? } ? ? ? ? private static final class Adapter<E> extends TypeAdapter<Collection<E>> { ? ? ? ? ? ? private final Gson gson; ? ? ? ? ? ? private final TypeToken listType; ? ? ? ? ? ? public Adapter(Gson context, TypeToken listType) { ? ? ? ? ? ? ? ? this.gson = context; ? ? ? ? ? ? ? ? this.listType = listType; ? ? ? ? ? ? } ? ? ? ? ? ? @Override public Collection<E> read(JsonReader in) throws IOException { ? ? ? ? ? ? ? ? if (in.peek() == JsonToken.NULL) { ? ? ? ? ? ? ? ? ? ? in.nextNull(); ? ? ? ? ? ? ? ? ? ? return null; ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? List<E> list = gson.fromJson(in.nextString(), listType.getType()); ? ? ? ? ? ? ? ? return list; ? ? ? ? ? ? } ? ? ? ? ? ? @Override public void write(JsonWriter out, Collection<E> collection) throws IOException { ? ? ? ? ? ? ? ? if (collection == null) { ? ? ? ? ? ? ? ? ? ? out.nullValue(); ? ? ? ? ? ? ? ? ? ? return; ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? out.value(gson.toJson(collection)); ? ? ? ? ? ? } ? ? ? ? } ? ? }
方式三-簡(jiǎn)單寫法
private static class CollectionStringTypeAdapterFactory implements TypeAdapterFactory { ? ? ? ? @Override ? ? ? ? public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) { ? ? ? ? ? ? return new TypeAdapter<T>() { ? ? ? ? ? ? ? ? @Override ? ? ? ? ? ? ? ? public void write(JsonWriter out, T value) throws IOException { ? ? ? ? ? ? ? ? ? ? if (value == null) { ? ? ? ? ? ? ? ? ? ? ? ? out.nullValue(); ? ? ? ? ? ? ? ? ? ? ? ? return; ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? gson.getAdapter(type).write(out, value); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? @Override ? ? ? ? ? ? ? ? public T read(JsonReader in) throws IOException { ? ? ? ? ? ? ? ? ? ? if (in.peek() == JsonToken.NULL) { ? ? ? ? ? ? ? ? ? ? ? ? return null; ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? if (in.peek() == JsonToken.BEGIN_ARRAY) { ? ? ? ? ? ? ? ? ? ? ? ? return gson.getAdapter(type).read(in); ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? T collection = gson.fromJson(in.nextString(), type.getType()); ? ? ? ? ? ? ? ? ? ? return collection; ? ? ? ? ? ? ? ? } ? ? ? ? ? ? }; ? ? ? ? } ? ? }
測(cè)試用例如下所示:
@Test ? ? public void testGson1() { ? ? ? ? Gson gson = new Gson(); ? ? ? ? RequestParams requestParam; ? ? ? ? String json; ? ? ? ? // 1.自動(dòng)將string轉(zhuǎn)為屬性的List ? ? ? ? json = "{\"id\": \"000000\",\"types\": \"[{\\\"name\\\":\\\"name1\\\",\\\"list\\\":[1,2]},{\\\"name\\\":\\\"name2\\\",\\\"list\\\":[3,4]}]\",\"keywordIds\": \"[12,13]\"}"; ? ? ? ? System.out.println(json); ? ? ? ? requestParam = gson.fromJson(json, new TypeToken<RequestParams>() {}.getType()); ? ? ? ? Assert.assertTrue(requestParam.getTypes().get(0).getClass().getName().indexOf("TypeItem") >= 0); ? ? ? ? System.out.println(gson.toJson(requestParam)); ? ? ? ? // 2.jsonArray也可以轉(zhuǎn)為L(zhǎng)ist ? ? ? ? json = "{\"id\": \"000000\",\"keywordIds\": [12,13],\"types\": [{\"name\":\"name1\",\"list\":[1,2]},{\"name\":\"name2\",\"list\":[3,4]}]}"; ? ? ? ? requestParam = gson.fromJson(json, new TypeToken<RequestParams>() {}.getType()); ? ? ? ? Assert.assertTrue(requestParam.getTypes().get(0).getClass().getName().indexOf("TypeItem") >= 0); ? ? ? ? System.out.println(gson.toJson(requestParam)); ? ? ? ? // 3.換行的方式呢 ? ? ? ? json = "{\n" + ? ? ? ? ? ? ? ? "\t\"id\": \"000000\",\n" + ? ? ? ? ? ? ? ? "\t\"keywordIds\": [12,13],\n" + ? ? ? ? ? ? ? ? "\t\"types\": [{\"name\":\"name1\",\"list\":[1,2]},{\"name\":\"name2\",\"list\":[3,4]}]\n" + ? ? ? ? ? ? ? ? "}"; ? ? ? ? requestParam = gson.fromJson(json, new TypeToken<RequestParams>() {}.getType()); ? ? ? ? Assert.assertTrue(requestParam.getTypes().get(0).getClass().getName().indexOf("TypeItem") >= 0); ? ? ? ? System.out.println(gson.toJson(requestParam)); ? ? ? ? // 4.能否將List里面的Integer變成String呢 ? ? ? ? json = "{\n" + ? ? ? ? ? ? ? ? "\t\"id\": \"000000\",\n" + ? ? ? ? ? ? ? ? "\t\"keywordIds\": [12,13],\n" + ? ? ? ? ? ? ? ? "\t\"types\": [{\"name\":\"name1\",\"list1\":[1,2]},{\"name\":\"name2\",\"list1\":[3,4]}]\n" + ? ? ? ? ? ? ? ? "}"; ? ? ? ? requestParam = gson.fromJson(json, new TypeToken<RequestParams>() {}.getType()); ? ? ? ? Assert.assertTrue(requestParam.getTypes().get(0).getClass().getName().indexOf("TypeItem") >= 0); ? ? ? ? System.out.println(gson.toJson(requestParam)); ? ? ? ? // 5.能否將List里面的Integer變成String ? ? ? ? json = "{\n" + ? ? ? ? ? ? ? ? "\t\"id\": \"000000\",\n" + ? ? ? ? ? ? ? ? "\t\"keywordIds1\": [12,13],\n" + ? ? ? ? ? ? ? ? "\t\"types\": [{\"name\":\"name1\",\"list1\":[1,2]},{\"name\":\"name2\",\"list1\":[3,4]}]\n" + ? ? ? ? ? ? ? ? "}"; ? ? ? ? requestParam = gson.fromJson(json, new TypeToken<RequestParams>() {}.getType()); ? ? ? ? Assert.assertTrue(requestParam.getTypes().get(0).getClass().getName().indexOf("TypeItem") >= 0); ? ? ? ? System.out.println(gson.toJson(requestParam)); ? ? ? ? // 6.自動(dòng)將string轉(zhuǎn)為屬性的List, 并且list里面的Integer變?yōu)镾tring ? ? ? ? json = "{\"id\": \"000000\",\"types\": \"[{\\\"name\\\":\\\"name1\\\",\\\"list1\\\":[1,2]},{\\\"name\\\":\\\"name2\\\",\\\"list1\\\":[3,4]}]\",\"keywordIds1\": \"[12,13]\"}"; ? ? ? ? System.out.println(json); ? ? ? ? requestParam = gson.fromJson(json, new TypeToken<RequestParams>() {}.getType()); ? ? ? ? Assert.assertTrue(requestParam.getTypes().get(0).getClass().getName().indexOf("TypeItem") >= 0); ? ? ? ? System.out.println(gson.toJson(requestParam)); ? ? } ? ? @Data ? ? public static class RequestParams { ? ? ? ? private String id; ? ? ? ? @JsonAdapter(CollectionStringTypeAdapterFactory.class) ? ? ? ? private List<TypeItem> types; ? ? ? ? @JsonAdapter(CollectionStringTypeAdapterFactory.class) ? ? ? ? private List<Integer> keywordIds; ? ? ? ? @JsonAdapter(CollectionStringTypeAdapterFactory.class) ? ? ? ? private List<String> keywordIds1; ? ? } ? ? @Data ? ? public static class TypeItem { ? ? ? ? private String name; ? ? ? ? private List<Integer> list; ? ? ? ? private List<String> list1; ? ? }
Gson注解
@SerializedName
主要應(yīng)用在Gson解析json字符串時(shí)。Gson能直接將json字符串解析成java對(duì)象或者集合,也能將java對(duì)象轉(zhuǎn)換為json字符串表示。例如有json數(shù)據(jù)如下:
{ ? ? "id":"1" ? ? "n":"zhangsan" ? ? "p":"123456" ? ? "s":"0" }
它能被解析到下面這個(gè)對(duì)象
public class User{ ? ? private String id; ? ? private String n; ? ? private String p; ? ? private string s; }
默認(rèn)在字段名相同的字段間解析,所以User類必須要這樣寫才能直接使用Gson解析出來,但是java對(duì)象里的屬性名和json里的字段名有時(shí)會(huì)不一樣。Gson提供注解的方法來解決這個(gè)問題。
public class User{ ? ? ? private String id; ? ? ? @SerializedName("n") ? ? private String userName; ? ? ? @SerializedName("p") ? ? private String password; ? ? ? @SerializedName("s") ? ? private String sex; }
Expose
通常與@SerializedName連用,當(dāng)我們不想把某個(gè)屬性包含到j(luò)son中時(shí)可以用。
public class UserSimple { ? ? ? @Expose() ? ? String name; // equals serialize & deserialize ? ? ? @Expose(serialize = false, deserialize = false) ? ? String email;? ? ? ? @Expose(serialize = false) ? ? int age;? ? ? ? @Expose(deserialize = false) ? ? boolean isDeveloper; // equals only serialize }
序列化的結(jié)果將只有name和isDeveloper出現(xiàn)在json中,因?yàn)閟erialize都是false。反序列化時(shí),java對(duì)象將只會(huì)擁有json中的name和age,因?yàn)閐iserialze是true。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
基于MybatisPlus插件TenantLineInnerInterceptor實(shí)現(xiàn)多租戶功能
這篇文章主要介紹了基于MybatisPlus插件TenantLineInnerInterceptor實(shí)現(xiàn)多租戶功能,需要的朋友可以參考下2021-11-11SpringMVC HttpMessageConverter報(bào)文信息轉(zhuǎn)換器
??HttpMessageConverter???,報(bào)文信息轉(zhuǎn)換器,將請(qǐng)求報(bào)文轉(zhuǎn)換為Java對(duì)象,或?qū)ava對(duì)象轉(zhuǎn)換為響應(yīng)報(bào)文。???HttpMessageConverter???提供了兩個(gè)注解和兩個(gè)類型:??@RequestBody,@ResponseBody???,??RequestEntity,ResponseEntity??2023-01-01SpringBoot啟動(dòng)報(bào)錯(cuò)Failed to determine a suitable driver class
這篇文章主要介紹了SpringBoot啟動(dòng)報(bào)錯(cuò)Failed to determine a suitable driver class,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-05-05logstash將mysql數(shù)據(jù)同步到elasticsearch方法詳解
這篇文章主要為大家介紹了logstash將mysql數(shù)據(jù)同步到elasticsearch方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12mybatis+springboot中使用mysql的實(shí)例
在軟件開發(fā)中,數(shù)據(jù)庫的引入是必不可少的,這里來展現(xiàn)一下通過mybatis框架在springboot中使用mysql,具有一定的參考價(jià)值,感興趣的可以了解一下2021-07-07Java基礎(chǔ)入門篇之邏輯控制練習(xí)題與猜數(shù)字游戲
猜數(shù)字游戲是一款經(jīng)典的游戲,該游戲說簡(jiǎn)單也很簡(jiǎn)單,說不簡(jiǎn)單確實(shí)也很難,這篇文章主要給大家介紹了關(guān)于Java基礎(chǔ)入門篇之邏輯控制練習(xí)題與猜數(shù)字游戲的相關(guān)資料,需要的朋友可以參考下2023-06-06解析SpringBoot中使用LoadTimeWeaving技術(shù)實(shí)現(xiàn)AOP功能
這篇文章主要介紹了SpringBoot中使用LoadTimeWeaving技術(shù)實(shí)現(xiàn)AOP功能,AOP面向切面編程,通過為目標(biāo)類織入切面的方式,實(shí)現(xiàn)對(duì)目標(biāo)類功能的增強(qiáng),本文給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-09-09詳解Spring Boot + Mybatis 實(shí)現(xiàn)動(dòng)態(tài)數(shù)據(jù)源
這篇文章主要介紹了Spring Boot + Mybatis 實(shí)現(xiàn)動(dòng)態(tài)數(shù)據(jù)源,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04