1
16 package com.google.gson.internal.bind;
17
18 import java.io.IOException;
19 import java.lang.reflect.Type;
20 import java.lang.reflect.TypeVariable;
21
22 import com.google.gson.Gson;
23 import com.google.gson.TypeAdapter;
24 import com.google.gson.reflect.TypeToken;
25 import com.google.gson.stream.JsonReader;
26 import com.google.gson.stream.JsonWriter;
27
28 final class TypeAdapterRuntimeTypeWrapper<T> extends TypeAdapter<T> {
29 private final Gson context;
30 private final TypeAdapter<T> delegate;
31 private final Type type;
32
33 TypeAdapterRuntimeTypeWrapper(Gson context, TypeAdapter<T> delegate, Type type) {
34 this.context = context;
35 this.delegate = delegate;
36 this.type = type;
37 }
38
39 @Override
40 public T read(JsonReader in) throws IOException {
41 return delegate.read(in);
42 }
43
44 @SuppressWarnings({"rawtypes", "unchecked"})
45 @Override
46 public void write(JsonWriter out, T value) throws IOException {
47
48
49
50
51
52
53 TypeAdapter chosen = delegate;
54 Type runtimeType = getRuntimeTypeIfMoreSpecific(type, value);
55 if (runtimeType != type) {
56 TypeAdapter runtimeTypeAdapter = context.getAdapter(TypeToken.get(runtimeType));
57 if (!(runtimeTypeAdapter instanceof ReflectiveTypeAdapterFactory.Adapter)) {
58
59 chosen = runtimeTypeAdapter;
60 } else if (!(delegate instanceof ReflectiveTypeAdapterFactory.Adapter)) {
61
62
63 chosen = delegate;
64 } else {
65
66 chosen = runtimeTypeAdapter;
67 }
68 }
69 chosen.write(out, value);
70 }
71
72
75 private Type getRuntimeTypeIfMoreSpecific(Type type, Object value) {
76 if (value != null
77 && (type == Object.class || type instanceof TypeVariable<?> || type instanceof Class<?>)) {
78 type = value.getClass();
79 }
80 return type;
81 }
82 }
83