Gson提供了丰富的预定义类型适配器,在对象和JSON串之间进行序列化和反序列化时,指定对象和字符串之间的转换方式,
DateTypeAdapter
public final class DateTypeAdapter extends TypeAdapter<Date> { public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() { @SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) { return typeToken.getRawType() == Date.class ? (TypeAdapter<T>) new DateTypeAdapter() : null; } }; private final DateFormat enUsFormat = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.US);//美国Locale private final DateFormat localFormat = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT);//本地Locale private final DateFormat iso8601Format = buildIso8601Format();//ISO8601时间格式 private static DateFormat buildIso8601Format() {//构造(ISO8601DateFormat DateFormat iso8601Format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US); iso8601Format.setTimeZone(TimeZone.getTimeZone("UTC")); return iso8601Format; } @Override public Date read(JsonReader in) throws IOException {//JsonReader中包含着要转换为Date的字符串 if (in.peek() == JsonToken.NULL) {//如果字符串为null in.nextNull();//将这个null消费完 return null; } return deserializeToDate(in.nextString());//将字符串反序列化为日期对象 } private synchronized Date deserializeToDate(String json) { try { return localFormat.parse(json);//首先尝试本地Locale } catch (ParseException ignored) { } try { return enUsFormat.parse(json);//再次尝试美国英语Locale } catch (ParseException ignored) { } try { return iso8601Format.parse(json); //最后尝试ISO8601时间格式 } catch (ParseException e) { throw new JsonSyntaxException(json, e); } } @Override public synchronized void write(JsonWriter out, Date value) throws IOException { if (value == null) { out.nullValue();//设置null值 return; } String dateFormatAsString = enUsFormat.format(value);//直接使用美国英语Locale将Date转换成为字符串 out.value(dateFormatAsString); } }
ArrayTypeAdapter
public final class ArrayTypeAdapter<E> extends TypeAdapter<Object> {//为什么是Object而不是E public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() { @SuppressWarnings({"unchecked", "rawtypes"}) public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) { Type type = typeToken.getType(); //如果type不是Array,返回null if (!(type instanceof GenericArrayType || type instanceof Class && ((Class<?>) type).isArray())) { return null; } Type componentType = $Gson$Types.getArrayComponentType(type); TypeAdapter<?> componentTypeAdapter = gson.getAdapter(TypeToken.get(componentType)); return new ArrayTypeAdapter( gson, componentTypeAdapter, $Gson$Types.getRawType(componentType)); } }; private final Class<E> componentType; private final TypeAdapter<E> componentTypeAdapter; public ArrayTypeAdapter(Gson context, TypeAdapter<E> componentTypeAdapter, Class<E> componentType) { this.componentTypeAdapter = new TypeAdapterRuntimeTypeWrapper<E>(context, componentTypeAdapter, componentType); this.componentType = componentType; } public Object read(JsonReader in) throws IOException { if (in.peek() == JsonToken.NULL) { in.nextNull(); return null; } List<E> list = new ArrayList<E>(); in.beginArray();//开始读数组 while (in.hasNext()) { E instance = componentTypeAdapter.read(in); list.add(instance); } in.endArray();//读数组结束 Object array = Array.newInstance(componentType, list.size()); for (int i = 0; i < list.size(); i++) { Array.set(array, i, list.get(i)); } return array; } @SuppressWarnings("unchecked") @Override public void write(JsonWriter out, Object array) throws IOException { if (array == null) { out.nullValue(); return; } out.beginArray(); for (int i = 0, length = Array.getLength(array); i < length; i++) { E value = (E) Array.get(array, i); componentTypeAdapter.write(out, value); } out.endArray(); } }
看到ArrayTypeAdapter的实现,可以说有点晕菜了,原因是对泛型不熟悉了,回头再看看泛型吧!!
SqlDateTypeAdapter
public final class SqlDateTypeAdapter extends TypeAdapter<java.sql.Date> { public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {//这个FACTORY干啥用的? @SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> typeToken) { return typeToken.getRawType() == java.sql.Date.class ? (TypeAdapter<T>) new SqlDateTypeAdapter() : null; } }; private final DateFormat format = new SimpleDateFormat("MMM d, yyyy"); //java.sql.Date与字符串转换的DateFormat @Override public synchronized java.sql.Date read(JsonReader in) throws IOException { if (in.peek() == JsonToken.NULL) { in.nextNull(); return null; } try { final long utilDate = format.parse(in.nextString()).getTime(); return new java.sql.Date(utilDate); } catch (ParseException e) { throw new JsonSyntaxException(e); } } @Override public synchronized void write(JsonWriter out, java.sql.Date value) throws IOException { out.value(value == null ? null : format.format(value));//将java.sql.Date对象转换成字符串,例如"Aug 13, 2014",所以默认的java.sql.Date转换为年月日 } }
ObjectTypeAdapter
import com.google.gson.Gson; import com.google.gson.TypeAdapter; import com.google.gson.TypeAdapterFactory; import com.google.gson.internal.LinkedTreeMap; import com.google.gson.reflect.TypeToken; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonToken; import com.google.gson.stream.JsonWriter; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; /** * Adapts types whose static type is only 'Object'. Uses getClass() on * serialization and a primitive/Map/List on deserialization. */ public final class ObjectTypeAdapter extends TypeAdapter<Object> { public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() { @SuppressWarnings("unchecked") public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) { if (type.getRawType() == Object.class) { // return (TypeAdapter<T>) new ObjectTypeAdapter(gson); } return null; } }; private final Gson gson; private ObjectTypeAdapter(Gson gson) { this.gson = gson; } @Override public Object read(JsonReader in) throws IOException { JsonToken token = in.peek();//判断字符串的实际类型 switch (token) { case BEGIN_ARRAY://如果是Array或者Map或者List,解析为ArrayList List<Object> list = new ArrayList<Object>(); in.beginArray(); while (in.hasNext()) { list.add(read(in)); } in.endArray(); return list; case BEGIN_OBJECT: //如果是Object,那么解析为Map,Map为String和Object的映射 Map<String, Object> map = new LinkedTreeMap<String, Object>(); in.beginObject(); while (in.hasNext()) { map.put(in.nextName(), read(in)); } in.endObject(); return map; case STRING://如果是字符串类型 return in.nextString(); case NUMBER://如果是数字类型 return in.nextDouble(); case BOOLEAN://如果是布尔类型 return in.nextBoolean(); case NULL://如果是Null in.nextNull(); return null; default: throw new IllegalStateException(); } } @SuppressWarnings("unchecked") @Override public void write(JsonWriter out, Object value) throws IOException { if (value == null) { out.nullValue(); return; } TypeAdapter<Object> typeAdapter = (TypeAdapter<Object>) gson.getAdapter(value.getClass());//得到value的实际类型对应的TypeAdapter if (typeAdapter instanceof ObjectTypeAdapter) {//因为是Object,没有数据字段可以写 out.beginObject(); out.endObject(); return; } typeAdapter.write(out, value);//调用实际的TypeAdapter进行写操作 } }
说明:下面的代码片段没有使用上面的ObjectTypeAdapter进行转换那么ObjectTypeAdapter究竟如何使用??
Map<String, String> map = new HashMap<String, String>(); map.put("IM1","QQ"); map.put("IM2","MSN"); Object obj = map; str = new Gson().toJson(obj); System.out.println(str);//{"IM2":"MSN","IM1":"QQ"} obj = new Integer(100); str = new Gson().toJson(obj); System.out.println(str);//100 obj = new Boolean(true); str = new Gson().toJson(obj); System.out.println(str);//true
常用数据类型适配器
如下的代码,对单个的obj进行序列化,得到的字符串是100,也能将"100"反序列化为Integer对象,这里并没有JSON串的格式,但是却实现了序列化和反序列化
Integer obj = new Integer(100); str = new Gson().toJson(obj); System.out.println(str);//100 obj = new Gson().fromJson(str,Integer.class); //obj是100
将基本数据类型的数据序列化为普通字符串,普通字符串序列化为基本数据类型,这是如何做到的呢?Gson在TypeAdapters中定义了一系列的简单数据类型的类型适配器,
Integer/Long/Short/Boolean/String/BigDecimal/BitSet/Byte/Double/Float/InetAddress/Locale/StringBuffer/StringBuilder/Timestamp/URI/URL/Enum
默认的Gson对象内置了哪些类型适配器
Gson构造方法表明默认的Gson对象已经将上面提到的预定义类型适配器参加到Gson对象中
public Gson() { this(Excluder.DEFAULT, FieldNamingPolicy.IDENTITY, Collections.<Type, InstanceCreator<?>>emptyMap(), false, false, DEFAULT_JSON_NON_EXECUTABLE, true, false, false, LongSerializationPolicy.DEFAULT, Collections.<TypeAdapterFactory>emptyList()); } Gson(final Excluder excluder, final FieldNamingStrategy fieldNamingPolicy, final Map<Type, InstanceCreator<?>> instanceCreators, boolean serializeNulls, boolean complexMapKeySerialization, boolean generateNonExecutableGson, boolean htmlSafe, boolean prettyPrinting, boolean serializeSpecialFloatingPointValues, LongSerializationPolicy longSerializationPolicy, List<TypeAdapterFactory> typeAdapterFactories) { this.constructorConstructor = new ConstructorConstructor(instanceCreators); this.serializeNulls = serializeNulls; this.generateNonExecutableJson = generateNonExecutableGson; this.htmlSafe = htmlSafe; this.prettyPrinting = prettyPrinting; List<TypeAdapterFactory> factories = new ArrayList<TypeAdapterFactory>(); // built-in type adapters that cannot be overridden factories.add(TypeAdapters.JSON_ELEMENT_FACTORY); factories.add(ObjectTypeAdapter.FACTORY); // the excluder must precede all adapters that handle user-defined types factories.add(excluder); // user's type adapters factories.addAll(typeAdapterFactories); // type adapters for basic platform types factories.add(TypeAdapters.STRING_FACTORY); factories.add(TypeAdapters.INTEGER_FACTORY); factories.add(TypeAdapters.BOOLEAN_FACTORY); factories.add(TypeAdapters.BYTE_FACTORY); factories.add(TypeAdapters.SHORT_FACTORY); factories.add(TypeAdapters.newFactory(long.class, Long.class, longAdapter(longSerializationPolicy))); factories.add(TypeAdapters.newFactory(double.class, Double.class, doubleAdapter(serializeSpecialFloatingPointValues))); factories.add(TypeAdapters.newFactory(float.class, Float.class, floatAdapter(serializeSpecialFloatingPointValues))); factories.add(TypeAdapters.NUMBER_FACTORY); factories.add(TypeAdapters.CHARACTER_FACTORY); factories.add(TypeAdapters.STRING_BUILDER_FACTORY); factories.add(TypeAdapters.STRING_BUFFER_FACTORY); factories.add(TypeAdapters.newFactory(BigDecimal.class, TypeAdapters.BIG_DECIMAL)); factories.add(TypeAdapters.newFactory(BigInteger.class, TypeAdapters.BIG_INTEGER)); factories.add(TypeAdapters.URL_FACTORY); factories.add(TypeAdapters.URI_FACTORY); factories.add(TypeAdapters.UUID_FACTORY); factories.add(TypeAdapters.LOCALE_FACTORY); factories.add(TypeAdapters.INET_ADDRESS_FACTORY); factories.add(TypeAdapters.BIT_SET_FACTORY); factories.add(DateTypeAdapter.FACTORY); factories.add(TypeAdapters.CALENDAR_FACTORY); factories.add(TimeTypeAdapter.FACTORY); factories.add(SqlDateTypeAdapter.FACTORY); factories.add(TypeAdapters.TIMESTAMP_FACTORY); factories.add(ArrayTypeAdapter.FACTORY); factories.add(TypeAdapters.ENUM_FACTORY); factories.add(TypeAdapters.CLASS_FACTORY); // type adapters for composite and user-defined types factories.add(new CollectionTypeAdapterFactory(constructorConstructor)); factories.add(new MapTypeAdapterFactory(constructorConstructor, complexMapKeySerialization)); factories.add(new ReflectiveTypeAdapterFactory( constructorConstructor, fieldNamingPolicy, excluder)); this.factories = Collections.unmodifiableList(factories); }
注册自定义类型适配器
使用方法Gson gson = new GsonBuilder().registerTypeAdapter(Type type, Object typeAdapter),例如注册自定义的日期和Long的类型适配器
Gson gson = new GsonBuilder().registerTypeAdapter(Date.class, new DateLongTypeAdapter())
总结:
1. 泛型是理解Gson类型适配器乃至整个Gson的序列化和发序列化的根本,比如ArrayTypeAdapter
2. 什么样的对象会用到ObjectTypeAdapter进行序列化和反序列化
相关推荐
FX Gson是一组类型适配器,用于将JavaFX属性序列化为其值,并将值反序列化为属性。 FX Gson只需删除属性“包装”,然后将值的序列化委托给Gson。 这意味着在序列化该类型的属性时,将考虑您添加到Gson的有关该类型...
一个Demo让你清楚了解Gson解析,Volley框架的使用,UniversalImageLOader框架的使用,送你一个万能的通用适配器,使用简单,扩展性强!
Gson解析网络数据显示到listview上,加入万能适配器,适配器就10行,大家可以复制包用,在log日记查看完整的Json数据,listview上我显示了title给大家看效果,适配器只要10行左右,简单易懂。
ext-gson是及更高版本的简单扩展库,其中包括以下库的一些扩展: ... AbstractBoundTypeAdapterFactory绑定到特定类型的类型适配器工厂超类,以摆脱@SuppressWarnings("unchecked")样板; AlwaysListType
根据 AOSP 代码样式指南,声明类型适配器和 GSON 的一些名称转换规则。 用法 public class SomeModel { private static final Gson GSON = AospGsonBuilder . buildExternalUseGson(); public String serialize ...
Stag Stag通过为模型对象自动生成无反射TypeAdapter来提高Gson性能。 为什么要建造雄鹿? Gson是必不可少的JSON解析库。 它通过自动为模型对象生成无反射TypeAdapter来大大简化Stag Stag改善Gson性能。 为什么要建造...
它已经实现了常见的 Volley 类: VolleyManager :封装 RequestQueue 和其他排球功能的单例类GsonRequest :用于 json 请求的 Volley 适配器,将由 Gson 解析为 Java 对象。 LruBitmapCache :内存中 lru 缓存的...
这个简易的新闻客户端运用了万能适配器、Gson解析等知识,是一次对前面所讲的内容的综合运用。
添加了用于请求构造URL和有效负载的流畅API 使用Jackson或Gson添加请求和响应... 使用基于baseUrl,Jackson或Gson的JSON主体适配器logger创建HttpClientContext。 public HttpClientContext client() { return HttpC
精仿今日头条 精仿今日头条,数据是抓取今日头条App的数据。使用RxJava Retrofit MVP开发的开源项目...BaseRecyclerViewAdapterHelper(ReclerView万能适配器) StateView(用于几种状态布局的切换) JieCaoVideoPlayer(视
本次项目实现了一个简单的网络视频播放器,调用的是高度自定义的视频框架...获取到数据源后,我们再创建适配器,给列表设置下适配器,加载网络数据,从而实现了网络视频的播放。非常适合小白进行模仿学习。
指定自己的 gson 适配器以允许解组自定义配置。 命令行选项: 显示配置文件 - 列出每个配置文件及其包含的阶段列表。 显示阶段 - 列出每个阶段的名称和实现类 show build - 打印构建脚本文件 显示帮助 - 打印用法 ...
:glowing_star: :GSON爱好者的理想选择,最适合应用内存储或高级用户配置 :相当有限,但仍然可以正常工作,没有漂亮的印刷品,可能最适合简单的应用内存储 豪康 :对使用人类优化配置对象表示法,但要注意限制 ...
LastFmTopTracks Android 上 LastFm Artist TopTracks 的 Restful API 改造 + GSON + 毕加索自定义适配器 + ListView 享受!
Adapter(各种listView的适配器) model(gson解析所用到的javabean) ui(activity) utils(工具类:包括下载用的AsynTask的子类,Imagecache的子类,及网络访问封装的HttpHelper) view(fragment) 存在问题: listView...
此软件包取决于Google GSON,因为它作为OSGi捆绑包分发,因此应按原样使用。 为了方便起见,可以从获得内容包。 记录中 默认情况下,Retrofit将记录到System.out 。 将它通过标准吊带/ AEM测井系统记录,该束包括...
首先倒入一个依赖: compile ‘com.youth.banner:banner:1.4.9’ 添加的权限: 布局文件: <com.youth.banner.Banner android:id=@+id/banner_id android:layout_width=match_parent
leetcode下载 android_address office365++ study kotlin 算法练习 Framework ...支持recyclerView的各种拓展,包括上拉加载、adapter适配器、多布局等 Permission Android6.0后的动态权限请求 ImmersionBa
Gson 数据结构 树 栈 链表 队列 图 操作系统 linux 代码控制 自动化代码检查 sonar 代码规范 阿里巴巴Java开发规范手册 UMPAY——编码规范 日志规范 异常规范 网络 协议 TCP/IP HTTP hession ...
该应用程序主要有7个软件包适配器具有用于Recycler View的适配器,用于显示动态文章Api具有2类和on接口,其中包括改造客户端和Api功能。 模型包包括用于使用Gson库将数据从json映射到类的所有模型类。 存储库包含...