<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
可以通過自定義TypeAdapter和TypeAdapterFactory的方式,自定義gson的序列化和反序列規則,TypeAdapterFactory可以拿到上下文gson、TokenType型別;
也可以通過繼承JsonReader重新寫一次程式碼,在beginArray和endArray想辦法跳過array的string形式的左右 雙引號", gson.fromJson(myJsonReader, Type)也可以實現 解析時自動將String變為List,但採用註解@JsonAdapter的方式更為正規一些;
json字串:
{ "cityIds": "[1,2,1001,13131]", "types": "[{"name": "biz","details": [1]}]" }
java物件定義:
@Data public static class RequestParams { // json字串裡對應的是String private List<TypeItem> types; private List<Integer> cityIds; } @Data public static class TypeItem { private String name; private List<Integer> details; }
可以看到json裡面cityIds和types都是String,而pojo裡則是List,使用gson的fromJson將json轉為pojo會發生報錯
@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的時候能使用到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(); } } }
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)); } } }
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; } }; } }
測試用例如下所示:
@Test public void testGson1() { Gson gson = new Gson(); RequestParams requestParam; String json; // 1.自動將string轉為屬性的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也可以轉為List 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.自動將string轉為屬性的List, 並且list裡面的Integer變為String 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解析json字串時。Gson能直接將json字串解析成java物件或者集合,也能將java物件轉換為json字串表示。例如有json資料如下:
{ "id":"1" "n":"zhangsan" "p":"123456" "s":"0" }
它能被解析到下面這個物件
public class User{ private String id; private String n; private String p; private string s; }
預設在欄位名相同的欄位間解析,所以User類必須要這樣寫才能直接使用Gson解析出來,但是java物件裡的屬性名和json裡的欄位名有時會不一樣。Gson提供註解的方法來解決這個問題。
public class User{ private String id; @SerializedName("n") private String userName; @SerializedName("p") private String password; @SerializedName("s") private String sex; }
通常與@SerializedName連用,當我們不想把某個屬性包含到json中時可以用。
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 }
序列化的結果將只有name和isDeveloper出現在json中,因為serialize都是false。反序列化時,java物件將只會擁有json中的name和age,因為diserialze是true。
以上為個人經驗,希望能給大家一個參考,也希望大家多多支援it145.com。
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45