Gson 使用问题记录

  1. GSON 不能序列化 anonymous and local classes:
public static void main(String[] args) {
		Gson gson = new GsonBuilder().serializeNulls().create();
		class CA {
			private String obj;

			public String getObj() {
				return obj;
			}

			public void setObj(String obj) {
				this.obj = obj;
			}
		}
		CA c = new CA();
		c.setObj("123");
		System.out.println(gson.toJson(c));
		// null
}

com.google.gson.internal.Excluder

/**
 * This class selects which fields and types to omit. It is configurable,
 * supporting version attributes {@link Since} and {@link Until}, modifiers,
 * synthetic fields, anonymous and local classes, inner classes, and fields with
 * the {@link Expose} annotation.
 *
 * <p>This class is a type adapter factory; types that are excluded will be
 * adapted to null. It may delegate to another type adapter if only one
 * direction is excluded.
 *
 * @author Joel Leitch
 * @author Jesse Wilson
 */
public final class Excluder implements TypeAdapterFactory, Cloneable {
	  public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> type) {
    Class<?> rawType = type.getRawType();
    boolean excludeClass = excludeClassChecks(rawType);

    final boolean skipSerialize = excludeClass || excludeClassInStrategy(rawType, true);
    final boolean skipDeserialize = excludeClass ||  excludeClassInStrategy(rawType, false);

    if (!skipSerialize && !skipDeserialize) {
      return null;
    }

    return new TypeAdapter<T>() {
      /** The delegate is lazily created because it may not be needed, and creating it may fail. */
      private TypeAdapter<T> delegate;

      @Override public T read(JsonReader in) throws IOException {
        if (skipDeserialize) {
          in.skipValue();
          return null;
        }
        return delegate().read(in);
      }

      @Override public void write(JsonWriter out, T value) throws IOException {
        if (skipSerialize) {
          out.nullValue();
          return;
        }
        delegate().write(out, value);
      }

      private TypeAdapter<T> delegate() {
        TypeAdapter<T> d = delegate;
        return d != null
            ? d
            : (delegate = gson.getDelegateAdapter(Excluder.this, type));
      }
    };
  }
	  private boolean excludeClassChecks(Class<?> clazz) {
      if (version != Excluder.IGNORE_VERSIONS && !isValidVersion(clazz.getAnnotation(Since.class), clazz.getAnnotation(Until.class))) {
          return true;
      }

      if (!serializeInnerClasses && isInnerClass(clazz)) {
          return true;
      }

      if (isAnonymousOrLocal(clazz)) {
          return true;
      }

      return false;
  }
	  private boolean isAnonymousOrLocal(Class<?> clazz) {
    return !Enum.class.isAssignableFrom(clazz)
        && (clazz.isAnonymousClass() || clazz.isLocalClass());
   }
}

而Excluder(TypeAdapter)在gson 中也设置了不可以被绕过 GSON:

public final class Gson {
	 /**
   * Returns the type adapter for {@code} type.
   *
   * @throws IllegalArgumentException if this GSON cannot serialize and
   *     deserialize {@code type}.
   */
  @SuppressWarnings("unchecked")
  public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {
    TypeAdapter<?> cached = typeTokenCache.get(type == null ? NULL_KEY_SURROGATE : type);
    if (cached != null) {
      return (TypeAdapter<T>) cached;
    }

    Map<TypeToken<?>, FutureTypeAdapter<?>> threadCalls = calls.get();
    boolean requiresThreadLocalCleanup = false;
    if (threadCalls == null) {
      threadCalls = new HashMap<TypeToken<?>, FutureTypeAdapter<?>>();
      calls.set(threadCalls);
      requiresThreadLocalCleanup = true;
    }

    // the key and value type parameters always agree
    FutureTypeAdapter<T> ongoingCall = (FutureTypeAdapter<T>) threadCalls.get(type);
    if (ongoingCall != null) {
      return ongoingCall;
    }

    try {
      FutureTypeAdapter<T> call = new FutureTypeAdapter<T>();
      threadCalls.put(type, call);

      for (TypeAdapterFactory factory : factories) {
        TypeAdapter<T> candidate = factory.create(this, type);
        if (candidate != null) {
          call.setDelegate(candidate);
          typeTokenCache.put(type, candidate);
          return candidate;
        }
      }
      throw new IllegalArgumentException("GSON (" + GsonBuildConfig.VERSION + ") cannot handle " + type);
    } finally {
      threadCalls.remove(type);

      if (requiresThreadLocalCleanup) {
        calls.remove();
      }
    }
  }

	Gson(final Excluder excluder, final FieldNamingStrategy fieldNamingStrategy,
      final Map<Type, InstanceCreator<?>> instanceCreators, boolean serializeNulls,
      boolean complexMapKeySerialization, boolean generateNonExecutableGson, boolean htmlSafe,
      boolean prettyPrinting, boolean lenient, boolean serializeSpecialFloatingPointValues,
      LongSerializationPolicy longSerializationPolicy, String datePattern, int dateStyle,
      int timeStyle, List<TypeAdapterFactory> builderFactories,
      List<TypeAdapterFactory> builderHierarchyFactories,
      List<TypeAdapterFactory> factoriesToBeAdded) {
    this.excluder = excluder;
    this.fieldNamingStrategy = fieldNamingStrategy;
    this.instanceCreators = instanceCreators;
    this.constructorConstructor = new ConstructorConstructor(instanceCreators);
    this.serializeNulls = serializeNulls;
    this.complexMapKeySerialization = complexMapKeySerialization;
    this.generateNonExecutableJson = generateNonExecutableGson;
    this.htmlSafe = htmlSafe;
    this.prettyPrinting = prettyPrinting;
    this.lenient = lenient;
    this.serializeSpecialFloatingPointValues = serializeSpecialFloatingPointValues;
    this.longSerializationPolicy = longSerializationPolicy;
    this.datePattern = datePattern;
    this.dateStyle = dateStyle;
    this.timeStyle = timeStyle;
    this.builderFactories = builderFactories;
    this.builderHierarchyFactories = builderHierarchyFactories;

    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);

    // users' type adapters
    factories.addAll(factoriesToBeAdded);
	...
}

gson 不序列化匿名 和局部类的原因是觉得 局部类会存在一个父类的引用,这会在系列化的时候导致错误的循环。 https://github.com/google/gson/issues/298

因此,这里只有在进行序列化之前绕过匿名和局部类。

转载于:https://my.oschina.net/yuyizyk/blog/2248597

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
包含以下java源文件: com.google.gson.DefaultDateTypeAdapter.class com.google.gson.ExclusionStrategy.class com.google.gson.FieldAttributes.class com.google.gson.FieldNamingPolicy.class com.google.gson.FieldNamingStrategy.class com.google.gson.Gson.class com.google.gson.GsonBuilder.class com.google.gson.InstanceCreator.class com.google.gson.JsonArray.class com.google.gson.JsonDeserializationContext.class com.google.gson.JsonDeserializer.class com.google.gson.JsonElement.class com.google.gson.JsonIOException.class com.google.gson.JsonNull.class com.google.gson.JsonObject.class com.google.gson.JsonParseException.class com.google.gson.JsonParser.class com.google.gson.JsonPrimitive.class com.google.gson.JsonSerializationContext.class com.google.gson.JsonSerializer.class com.google.gson.JsonStreamParser.class com.google.gson.JsonSyntaxException.class com.google.gson.LongSerializationPolicy.class com.google.gson.TreeTypeAdapter.class com.google.gson.TypeAdapter.class com.google.gson.TypeAdapterFactory.class com.google.gson.annotations.Expose.class com.google.gson.annotations.SerializedName.class com.google.gson.annotations.Since.class com.google.gson.annotations.Until.class com.google.gson.internal.ConstructorConstructor.class com.google.gson.internal.Excluder.class com.google.gson.internal.JsonReaderInternalAccess.class com.google.gson.internal.LazilyParsedNumber.class com.google.gson.internal.LinkedTreeMap.class com.google.gson.internal.ObjectConstructor.class com.google.gson.internal.Primitives.class com.google.gson.internal.Streams.class com.google.gson.internal.UnsafeAllocator.class com.google.gson.internal.bind.ArrayTypeAdapter.class com.google.gson.internal.bind.CollectionTypeAdapterFactory.class com.google.gson.internal.bind.DateTypeAdapter.class com.google.gson.internal.bind.JsonTreeReader.class com.google.gson.internal.bind.JsonTreeWriter.class com.google.gson.internal.bind.MapTypeAdapterFactory.class com.google.gson.internal.bind.ObjectTypeAdapter.class com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.class com.google.gson.internal.bind.SqlDateTypeAdapter.class com.google.gson.internal.bind.TimeTypeAdapter.class com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.class com.google.gson.internal.bind.TypeAdapters.class com.google.gson.reflect.TypeToken.class com.google.gson.stream.JsonReader.class com.google.gson.stream.JsonScope.class com.google.gson.stream.JsonToken.class com.google.gson.stream.JsonWriter.class com.google.gson.stream.MalformedJsonException.class

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值