Gson中@JsonAdater注解的几种方式总结

Gson中@JsonAdater注解的几种方式总结

目录

Gson @JsonAdater注解的几种方式

总结

问题描述

方式一

方式二-write原样

方式三-简单写法

Gson注解

@SerializedName

Expose

Gson @JsonAdater注解的几种方式 总结

可以通过自定义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();             }         }     } 方式二-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));             }         }     } 方式三-简单写法 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注解 @SerializedName

主要应用在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; } Expose

通常与@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。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持易知道(ezd.cc)。

推荐阅读

    如何使用GSON解析JSON数据

    如何使用GSON解析JSON数据目录添加依赖JSON数据介绍GsonFormat@SerializedName注解Gson的使用具体实例GSON是谷歌提供的一个开源库,可以