Gson中@JsonAdater注解的幾種方式總結(jié)
Gson @JsonAdater注解的幾種方式
總結(jié)
可以通過(guò)自定義TypeAdapter和TypeAdapterFactory的方式,自定義gson的序列化和反序列規(guī)則,TypeAdapterFactory可以拿到上下文gson、TokenType類(lèi)型;
也可以通過(guò)繼承JsonReader重新寫(xiě)一次代碼,在beginArray和endArray想辦法跳過(guò)array的string形式的左右 雙引號(hào)", gson.fromJson(myJsonReader, Type)也可以實(shí)現(xiàn) 解析時(shí)自動(dòng)將String變?yōu)長(zhǎng)ist,但采用注解@JsonAdapter的方式更為正規(guī)一些;
問(wèn)題描述
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)單寫(xiě)法
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類(lèi)必須要這樣寫(xiě)才能直接使用Gson解析出來(lái),但是java對(duì)象里的屬性名和json里的字段名有時(shí)會(huì)不一樣。Gson提供注解的方法來(lái)解決這個(gè)問(wèn)題。
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)文章
Java開(kāi)發(fā)深入分析講解二叉樹(shù)的遞歸和非遞歸遍歷方法
樹(shù)是一種重要的非線性數(shù)據(jù)結(jié)構(gòu),直觀地看,它是數(shù)據(jù)元素(在樹(shù)中稱為結(jié)點(diǎn))按分支關(guān)系組織起來(lái)的結(jié)構(gòu),很象自然界中的樹(shù)那樣。樹(shù)結(jié)構(gòu)在客觀世界中廣泛存在,如人類(lèi)社會(huì)的族譜和各種社會(huì)組織機(jī)構(gòu)都可用樹(shù)形象表示,本篇介紹二叉樹(shù)的遞歸與非遞歸遍歷的方法2022-05-05
java實(shí)現(xiàn)表單必填參數(shù)驗(yàn)證的方法
表單校驗(yàn)是很多注冊(cè)時(shí)必做的功能, 一般我們的處理都是很粗暴的寫(xiě)個(gè)if()判斷, 然后拋異常. 本文將介紹通過(guò)代理的思想, 用注解優(yōu)雅的處理非空判斷,感興趣的一起來(lái)了解一下2021-05-05
RestTemplate使用Proxy代理作為跳板發(fā)送請(qǐng)求
這篇文章主要為大家介紹了RestTemplate使用代理proxy作為跳板發(fā)送請(qǐng)求的方法示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2022-03-03
java基于netty NIO的簡(jiǎn)單聊天室的實(shí)現(xiàn)
這篇文章主要介紹了java基于netty NIO的簡(jiǎn)單聊天室的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07
基于spring boot 2和shiro實(shí)現(xiàn)身份驗(yàn)證案例
這篇文章主要介紹了基于spring boot 2和shiro實(shí)現(xiàn)身份驗(yàn)證案例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-04-04
Jmeter關(guān)聯(lián)實(shí)現(xiàn)及參數(shù)化使用解析
這篇文章主要介紹了Jmeter關(guān)聯(lián)實(shí)現(xiàn)及參數(shù)化使用解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08
SpringBoot整合Elasticsearch實(shí)現(xiàn)索引和文檔的操作方法
Elasticsearch 基于 Apache Lucene 構(gòu)建,采用 Java 編寫(xiě),并使用 Lucene 構(gòu)建索引、提供搜索功能,本文分步驟通過(guò)綜合案例給大家分享SpringBoot整合Elasticsearch的相關(guān)知識(shí),感興趣的朋友跟隨小編一起看看吧2021-05-05
SpringBoot+Redisson自定義注解一次解決重復(fù)提交問(wèn)題
項(xiàng)目中經(jīng)常會(huì)出現(xiàn)重復(fù)提交的問(wèn)題,本文主要介紹了SpringBoot+Redisson自定義注解一次解決重復(fù)提交問(wèn)題,具有一定的參考價(jià)值,感興趣的可以了解一下2024-03-03
Java循環(huán)終止的實(shí)現(xiàn)方式總結(jié)
循環(huán)是一種重復(fù)執(zhí)行一段代碼的結(jié)構(gòu),Java提供了四種主要的循環(huán)結(jié)構(gòu),本文主要來(lái)和大家介紹一下Java循環(huán)終止的實(shí)現(xiàn)方式,有需要的小伙伴可以參考一下2023-10-10

