-
Notifications
You must be signed in to change notification settings - Fork 123
/
SingleElementSafeListTypeAdapter.java
105 lines (93 loc) · 3.18 KB
/
SingleElementSafeListTypeAdapter.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package com.mapbox.api.geocoding.v5;
import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.internal.$Gson$Types;
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 com.google.gson.stream.MalformedJsonException;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
/**
* Similar to {@link com.google.gson.internal.bind.CollectionTypeAdapterFactory},
* safely adapts single element list represented as Json object or primitive.
*
* Note: unlike {@link com.google.gson.internal.bind.CollectionTypeAdapterFactory},
* this adapter does not perform advanced type analyse and always returns instance of ArrayList
* which may not work if it is used to deserialize JSON elements into another subtype of List
* (LinkedList for example).
*
* @param <E> collection element type
*
* @since 5.4.0
*/
class SingleElementSafeListTypeAdapter<E> extends TypeAdapter<List<E>> {
/**
* A type adapter factory instance for serialization/deserialization.
*/
static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
@Override
public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> typeToken) {
final Class<? super T> rawType = typeToken.getRawType();
if (!List.class.isAssignableFrom(rawType)) {
return null;
}
final Type elementType = $Gson$Types.getCollectionElementType(typeToken.getType(), rawType);
final TypeAdapter<?> elementTypeAdapter = gson.getAdapter(TypeToken.get(elementType));
@SuppressWarnings("unchecked")
final TypeAdapter<T> adapter =
(TypeAdapter<T>) new SingleElementSafeListTypeAdapter<>(elementTypeAdapter);
return adapter;
}
};
private final TypeAdapter<E> elementTypeAdapter;
private SingleElementSafeListTypeAdapter(final TypeAdapter<E> elementTypeAdapter) {
this.elementTypeAdapter = elementTypeAdapter;
}
@Override
public List<E> read(final JsonReader in) throws IOException {
final JsonToken token = in.peek();
final List<E> elements = new ArrayList<>();
switch (token) {
case BEGIN_ARRAY:
in.beginArray();
while (in.hasNext()) {
elements.add(elementTypeAdapter.read(in));
}
in.endArray();
return elements;
case BEGIN_OBJECT:
case STRING:
case NUMBER:
case BOOLEAN:
elements.add(elementTypeAdapter.read(in));
return elements;
case NULL:
in.nextNull();
return null;
case NAME:
case END_ARRAY:
case END_OBJECT:
case END_DOCUMENT:
throw new MalformedJsonException("Unexpected token: " + token);
default:
throw new IllegalStateException("Unprocessed token: " + token);
}
}
@Override
public void write(final JsonWriter out, final List<E> value) throws IOException {
if (value == null) {
out.nullValue();
return;
}
out.beginArray();
for (E element : value) {
elementTypeAdapter.write(out, element);
}
out.endArray();
}
}