1
16
17 package com.google.gson.internal.bind;
18
19 import com.google.gson.Gson;
20 import com.google.gson.JsonDeserializationContext;
21 import com.google.gson.JsonDeserializer;
22 import com.google.gson.JsonElement;
23 import com.google.gson.JsonParseException;
24 import com.google.gson.JsonSerializationContext;
25 import com.google.gson.JsonSerializer;
26 import com.google.gson.TypeAdapter;
27 import com.google.gson.TypeAdapterFactory;
28 import com.google.gson.internal.$Gson$Preconditions;
29 import com.google.gson.internal.Streams;
30 import com.google.gson.reflect.TypeToken;
31 import com.google.gson.stream.JsonReader;
32 import com.google.gson.stream.JsonWriter;
33 import java.io.IOException;
34 import java.lang.reflect.Type;
35
36
41 public final class TreeTypeAdapter<T> extends TypeAdapter<T> {
42 private final JsonSerializer<T> serializer;
43 private final JsonDeserializer<T> deserializer;
44 final Gson gson;
45 private final TypeToken<T> typeToken;
46 private final TypeAdapterFactory skipPast;
47 private final GsonContextImpl context = new GsonContextImpl();
48
49
50 private TypeAdapter<T> delegate;
51
52 public TreeTypeAdapter(JsonSerializer<T> serializer, JsonDeserializer<T> deserializer,
53 Gson gson, TypeToken<T> typeToken, TypeAdapterFactory skipPast) {
54 this.serializer = serializer;
55 this.deserializer = deserializer;
56 this.gson = gson;
57 this.typeToken = typeToken;
58 this.skipPast = skipPast;
59 }
60
61 @Override public T read(JsonReader in) throws IOException {
62 if (deserializer == null) {
63 return delegate().read(in);
64 }
65 JsonElement value = Streams.parse(in);
66 if (value.isJsonNull()) {
67 return null;
68 }
69 return deserializer.deserialize(value, typeToken.getType(), context);
70 }
71
72 @Override public void write(JsonWriter out, T value) throws IOException {
73 if (serializer == null) {
74 delegate().write(out, value);
75 return;
76 }
77 if (value == null) {
78 out.nullValue();
79 return;
80 }
81 JsonElement tree = serializer.serialize(value, typeToken.getType(), context);
82 Streams.write(tree, out);
83 }
84
85 private TypeAdapter<T> delegate() {
86 TypeAdapter<T> d = delegate;
87 return d != null
88 ? d
89 : (delegate = gson.getDelegateAdapter(skipPast, typeToken));
90 }
91
92
95 public static TypeAdapterFactory newFactory(TypeToken<?> exactType, Object typeAdapter) {
96 return new SingleTypeFactory(typeAdapter, exactType, false, null);
97 }
98
99
103 public static TypeAdapterFactory newFactoryWithMatchRawType(
104 TypeToken<?> exactType, Object typeAdapter) {
105
106 boolean matchRawType = exactType.getType() == exactType.getRawType();
107 return new SingleTypeFactory(typeAdapter, exactType, matchRawType, null);
108 }
109
110
114 public static TypeAdapterFactory newTypeHierarchyFactory(
115 Class<?> hierarchyType, Object typeAdapter) {
116 return new SingleTypeFactory(typeAdapter, null, false, hierarchyType);
117 }
118
119 private static final class SingleTypeFactory implements TypeAdapterFactory {
120 private final TypeToken<?> exactType;
121 private final boolean matchRawType;
122 private final Class<?> hierarchyType;
123 private final JsonSerializer<?> serializer;
124 private final JsonDeserializer<?> deserializer;
125
126 SingleTypeFactory(Object typeAdapter, TypeToken<?> exactType, boolean matchRawType,
127 Class<?> hierarchyType) {
128 serializer = typeAdapter instanceof JsonSerializer
129 ? (JsonSerializer<?>) typeAdapter
130 : null;
131 deserializer = typeAdapter instanceof JsonDeserializer
132 ? (JsonDeserializer<?>) typeAdapter
133 : null;
134 $Gson$Preconditions.checkArgument(serializer != null || deserializer != null);
135 this.exactType = exactType;
136 this.matchRawType = matchRawType;
137 this.hierarchyType = hierarchyType;
138 }
139
140 @SuppressWarnings("unchecked")
141 @Override
142 public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
143 boolean matches = exactType != null
144 ? exactType.equals(type) || matchRawType && exactType.getType() == type.getRawType()
145 : hierarchyType.isAssignableFrom(type.getRawType());
146 return matches
147 ? new TreeTypeAdapter<T>((JsonSerializer<T>) serializer,
148 (JsonDeserializer<T>) deserializer, gson, type, this)
149 : null;
150 }
151 }
152
153 private final class GsonContextImpl implements JsonSerializationContext, JsonDeserializationContext {
154 @Override public JsonElement serialize(Object src) {
155 return gson.toJsonTree(src);
156 }
157 @Override public JsonElement serialize(Object src, Type typeOfSrc) {
158 return gson.toJsonTree(src, typeOfSrc);
159 }
160 @SuppressWarnings("unchecked")
161 @Override public <R> R deserialize(JsonElement json, Type typeOfT) throws JsonParseException {
162 return (R) gson.fromJson(json, typeOfT);
163 }
164 };
165 }
166