`
bit1129
  • 浏览: 1067756 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

【Gson七】Gson预定义类型适配器

 
阅读更多

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进行序列化和反序列化

 

 

 

 

 

分享到:
评论

相关推荐

    利用Gson.jar快速将对象类型转换为Json

    - **类型适配器**:通过创建`TypeAdapter`并注册到`GsonBuilder`,可以完全控制特定类型的序列化和反序列化过程。 7. **注意事项** - 当对象包含循环引用时,Gson可能会导致无限递归错误。可以使用`@Expose`注解...

    通用适配器+Gson+Volley+UniversalImageLOader下载图片的Demo

    这个"通用适配器+Gson+Volley+UniversalImageLoader下载图片的Demo"提供了这四个关键领域的应用示例,帮助开发者深入理解并掌握这些技术。 首先,Gson是一个由Google提供的Java库,用于将Java对象转换为JSON格式,...

    om.google.gson.Gson Gson maven依赖

    3. **类型适配器(Type Adapters)**:Gson允许自定义类型适配器来处理特定类型的序列化和反序列化逻辑,比如日期、自定义类等。 4. **字段忽略**:通过注解`@Expose`可以控制哪些字段被序列化或反序列化。 5. **...

    fx-gson:一组Google Gson的类型适配器,使JavaFX属性序列化更加自然

    FX Gson是一组类型适配器,用于将JavaFX属性序列化为其值,并将值反序列化为属性。 FX Gson只需删除属性“包装”,然后将值的序列化委托给Gson。 这意味着在序列化该类型的属性时,将考虑您添加到Gson的有关该类型...

    com.google.gson.Gson 2.8.1 2.8.2 jar包 gson

    7. **Builder模式配置**:Gson通过`GsonBuilder`类提供了丰富的配置选项,如设置日期格式、启用或禁用特定特性,甚至注册自定义类型适配器。 8. **性能优化**:Gson 2.8.x系列版本持续优化了性能,包括更快的序列化...

    gson jar包下载

    Gson可以处理基本数据类型,如整型、浮点型、字符串,以及自定义的复杂对象。在处理复杂类型时,可以使用`@Expose`注解来指定哪些字段应被序列化或反序列化。 2. **自定义序列化与反序列化** 如果默认的转换规则...

    Gson 枚举类型的统一序列化/反序列化处理

    本篇文章将详细探讨如何通过自定义Gson适配器实现枚举类型的统一序列化和反序列化处理,无需预先定义枚举,也无需修改Gson源码。 首先,Gson是Google提供的一个开源库,用于在Java对象和JSON数据之间进行映射。默认...

    com.google.gson.Gson-2.8.2

    5. **日期/时间处理**:Gson提供内置的日期/时间类型适配器,可以方便地将日期对象转换为JSON格式,并能解析回日期对象。 6. **泛型支持**:Gson能够处理带有类型参数的类,即使这些类型信息在运行时可能丢失。 7....

    google-gson-2.2.4.zip

    3. **类型适配器**:Gson允许用户自定义类型适配器,以便处理特定类型的序列化和反序列化。这对于处理自定义日期格式、枚举类型或其他复杂数据结构尤其有用。 4. **字段映射**:Gson可以自动映射JSON键到Java类的...

    Google-Gson 2.2.4

    3. **类型适配器**:Gson提供自定义类型适配器,允许用户在序列化和反序列化过程中控制特定类型的转换行为。 4. **复杂类型处理**:Gson可以处理各种复杂的Java类型,包括数组、集合、Map、枚举以及嵌套对象等。 5...

    gson-2.8.6.zip

    4. **类型适配器(TypeAdapter)**:Gson允许用户自定义类型适配器,以处理特定类型的序列化和反序列化逻辑,特别是对于复杂或者自定义的Java类型。 5. **字段注解(Field Annotations)**:Gson支持通过在Java字段...

    谷歌 Gson2.8.0 依赖包、文档和源码

    它还提供了自定义类型适配器,使得处理特殊类型的数据更加灵活。此外,Gson的`JsonParser`类可以用于逐项解析JSON流,而`JsonElement`树模型则允许对JSON进行深度操作。 总之,谷歌Gson 2.8.0版本是一个强大的JSON...

    google json: gson

    类型适配器是Gson的另一种高级特性,可以精确控制特定类型的序列化和反序列化过程。它们通过继承`GsonBuilder`的`registerTypeAdapter()`方法来注册。 6. **日期和时间处理** Gson默认不支持Java的`Date`对象,但...

    gson-2.8.6.jar

    3. **类型适配器**:Gson允许你自定义数据转换规则,通过实现`JsonSerializer`和`JsonDeserializer`接口,可以控制特定类型的序列化和反序列化过程。 4. **注解支持**:Gson提供了丰富的注解,如`@Expose`用于指定...

    gson-2.2.4.jar

    - **类型适配器**:如果你需要更精细的控制转换过程,可以实现`TypeAdapter`接口,Gson会使用这些适配器进行特定类型的转换。 - **运行时类型信息**:Gson可以处理运行时的类型信息,允许将JSON转换为未知类型。 - *...

    Gson最新依赖jar(带源码)

    3. **类型适配器**:可以通过创建自定义的类型适配器来实现对特定类型数据的特殊处理。 4. **注解支持**:Gson支持多种注解,如`@SerializedName`、`@Expose`等,这些注解可以用来控制序列化和反序列化的过程。 ##...

    gson2.7相关jar包

    2. **类型适应性(Type Adapters)**:Gson 2.7支持自定义类型适配器,这使得开发者能够精确控制如何将特定Java类型转换为JSON以及如何从JSON反序列化。这对于处理复杂或非标准的JSON结构特别有用。 3. **序列化和...

    Google发布的强大的gson包

    3. **类型适配器**:Gson允许用户自定义数据转换规则,通过实现`JsonSerializer`和`JsonDeserializer`接口,可以控制特定类型的序列化和反序列化过程。 4. **字段注解**:Gson支持使用Java注解来控制哪些字段被序列...

    gson-gson-parent-2.10.1.tar.gz

    3. **类型适配器(TypeAdapter)**:Gson允许自定义数据类型的序列化和反序列化过程,通过实现`TypeAdapter`接口,可以对特定类型的数据进行特殊处理。 4. **字段命名策略**:Gson支持不同的字段命名策略,比如保持...

    利用Google Gson实现JSON字符串和对象之间相互转换

    在上述代码中,`MyCustomAdapter`是自定义的类型适配器,Gson会在序列化或反序列化`User`对象时调用这个适配器。 ### 处理复杂类型 Gson支持多种复杂类型的转换,如列表、映射等。例如,将一个`List&lt;User&gt;`转换为...

Global site tag (gtag.js) - Google Analytics