@@ -51,14 +51,14 @@ public <T> TypeAdapter<T> create(MiniGson context, TypeToken<T> type) {
51
51
return new ReflectiveTypeAdapter <T >(constructor , getBoundFields (context , type , raw ));
52
52
}
53
53
54
- private Map <String , BoundField <?> > getBoundFields (
54
+ private Map <String , BoundField > getBoundFields (
55
55
MiniGson context , TypeToken <?> type , Class <?> raw ) {
56
- Map <String , BoundField <?>> result = new LinkedHashMap <String , BoundField <?> >();
56
+ Map <String , BoundField > result = new LinkedHashMap <String , BoundField >();
57
57
while (raw != Object .class ) {
58
58
for (Field field : raw .getDeclaredFields ()) {
59
59
field .setAccessible (true ); // TODO: don't call setAccessible unless necessary
60
60
Type fieldType = $Gson$Types .resolve (type .getType (), raw , field .getGenericType ());
61
- BoundField <?> boundField = BoundField . create (context , field , TypeToken .get (fieldType ));
61
+ BoundField boundField = createBoundField (context , field , TypeToken .get (fieldType ));
62
62
result .put (boundField .name , boundField );
63
63
}
64
64
type = TypeToken .get ($Gson$Types .resolve (type .getType (), raw , raw .getGenericSuperclass ()));
@@ -69,13 +69,13 @@ private Map<String, BoundField<?>> getBoundFields(
69
69
};
70
70
71
71
private final Constructor <? super T > constructor ;
72
- private final Map <String , BoundField <?> > map ;
73
- private final BoundField <?> [] boundFields ;
72
+ private final Map <String , BoundField > map ;
73
+ private final BoundField [] boundFields ;
74
74
75
- ReflectiveTypeAdapter (Constructor <? super T > constructor , Map <String , BoundField <?> > map ) {
75
+ ReflectiveTypeAdapter (Constructor <? super T > constructor , Map <String , BoundField > map ) {
76
76
this .constructor = constructor ;
77
77
this .map = map ;
78
- this .boundFields = map .values ().toArray (new BoundField <?> [map .size ()]);
78
+ this .boundFields = map .values ().toArray (new BoundField [map .size ()]);
79
79
}
80
80
81
81
public T read (JsonReader reader ) throws IOException {
@@ -90,15 +90,19 @@ public T read(JsonReader reader) throws IOException {
90
90
// TODO: null out the other fields?
91
91
92
92
reader .beginObject ();
93
- while (reader .hasNext ()) {
94
- String name = reader .nextName ();
95
- BoundField <?> field = map .get (name );
96
- if (field == null ) {
97
- // TODO: define a better policy
98
- reader .skipValue ();
99
- } else {
100
- field .read (reader , instance );
93
+ try {
94
+ while (reader .hasNext ()) {
95
+ String name = reader .nextName ();
96
+ BoundField field = map .get (name );
97
+ if (field == null ) {
98
+ // TODO: define a better policy
99
+ reader .skipValue ();
100
+ } else {
101
+ field .read (reader , instance );
102
+ }
101
103
}
104
+ } catch (IllegalAccessException e ) {
105
+ throw new AssertionError ();
102
106
}
103
107
reader .endObject ();
104
108
return instance ;
@@ -111,45 +115,44 @@ public void write(JsonWriter writer, T value) throws IOException {
111
115
}
112
116
113
117
writer .beginObject ();
114
- for (BoundField <?> boundField : boundFields ) {
115
- writer .name (boundField .name );
116
- boundField .write (writer , value );
118
+ try {
119
+ for (BoundField boundField : boundFields ) {
120
+ writer .name (boundField .name );
121
+ boundField .write (writer , value );
122
+ }
123
+ } catch (IllegalAccessException e ) {
124
+ throw new AssertionError ();
117
125
}
118
126
writer .endObject ();
119
127
}
120
128
121
- static class BoundField <T > {
129
+ static BoundField createBoundField (
130
+ final MiniGson context , final Field field , final TypeToken <?> fieldType ) {
131
+ // special casing primitives here saves ~5% on Android...
132
+ return new BoundField (field .getName ()) {
133
+ final TypeAdapter <?> typeAdapter = context .getAdapter (fieldType );
134
+ @ SuppressWarnings ("unchecked" ) // the type adapter and field type always agree
135
+ @ Override void write (JsonWriter writer , Object value )
136
+ throws IOException , IllegalAccessException {
137
+ Object fieldValue = field .get (value );
138
+ ((TypeAdapter ) typeAdapter ).write (writer , fieldValue );
139
+ }
140
+ @ Override void read (JsonReader reader , Object value )
141
+ throws IOException , IllegalAccessException {
142
+ Object fieldValue = typeAdapter .read (reader );
143
+ field .set (value , fieldValue );
144
+ }
145
+ };
146
+ }
147
+
148
+ static abstract class BoundField {
122
149
final String name ;
123
- final Field field ;
124
- final TypeAdapter <T > typeAdapter ;
125
150
126
- BoundField (String name , Field field , TypeAdapter < T > typeAdapter ) {
151
+ protected BoundField (String name ) {
127
152
this .name = name ;
128
- this .field = field ;
129
- this .typeAdapter = typeAdapter ;
130
- }
131
-
132
- static <T > BoundField <T > create (MiniGson context , Field field , TypeToken <T > fieldType ) {
133
- return new BoundField <T >(field .getName (), field , context .getAdapter (fieldType ));
134
153
}
135
154
136
- void write (JsonWriter writer , Object value ) throws IOException {
137
- try {
138
- @ SuppressWarnings ("unchecked" ) // we previously verified that field is of type T
139
- T fieldValue = (T ) field .get (value );
140
- typeAdapter .write (writer , fieldValue );
141
- } catch (IllegalAccessException e ) {
142
- throw new AssertionError ();
143
- }
144
- }
145
-
146
- void read (JsonReader reader , Object value ) throws IOException {
147
- T fieldValue = typeAdapter .read (reader );
148
- try {
149
- field .set (value , fieldValue );
150
- } catch (IllegalAccessException e ) {
151
- throw new AssertionError ();
152
- }
153
- }
155
+ abstract void write (JsonWriter writer , Object value ) throws IOException , IllegalAccessException ;
156
+ abstract void read (JsonReader reader , Object value ) throws IOException , IllegalAccessException ;
154
157
}
155
158
}
0 commit comments