3838import java .lang .reflect .Type ;
3939import java .util .Collections ;
4040import java .util .Map ;
41+ import java .util .Set ;
4142
4243import static feign .Util .ensureClosed ;
43-
44+ import static feign .Util .resolveLastTypeParameter ;
45+
46+ /**
47+ * <h3>Custom type adapters</h3>
48+ * <br>
49+ * In order to specify custom json parsing,
50+ * {@code Gson} supports {@link TypeAdapter type adapters}. This module adds one
51+ * to read numbers in a {@code Map<String, Object>} as Integers. You can
52+ * customize further by adding additional set bindings to the raw type
53+ * {@code TypeAdapter}.
54+ *
55+ * <br>
56+ * Here's an example of adding a custom json type adapter.
57+ *
58+ * <pre>
59+ * @Provides(type = Provides.Type.SET)
60+ * TypeAdapter upperZone() {
61+ * return new TypeAdapter<Zone>() {
62+ *
63+ * @Override
64+ * public void write(JsonWriter out, Zone value) throws IOException {
65+ * throw new IllegalArgumentException();
66+ * }
67+ *
68+ * @Override
69+ * public Zone read(JsonReader in) throws IOException {
70+ * in.beginObject();
71+ * Zone zone = new Zone();
72+ * while (in.hasNext()) {
73+ * zone.put(in.nextName(), in.nextString().toUpperCase());
74+ * }
75+ * in.endObject();
76+ * return zone;
77+ * }
78+ * };
79+ * }
80+ * </pre>
81+ */
4482@ dagger .Module (library = true )
4583public final class GsonModule {
4684
@@ -87,8 +125,17 @@ private Object fromJson(JsonReader jsonReader, Type type) throws IOException {
87125 }
88126 }
89127
128+ @ Provides @ Singleton Gson gson (Set <TypeAdapter > adapters ) {
129+ GsonBuilder builder = new GsonBuilder ().setPrettyPrinting ();
130+ for (TypeAdapter <?> adapter : adapters ) {
131+ Type type = resolveLastTypeParameter (adapter .getClass (), TypeAdapter .class );
132+ builder .registerTypeAdapter (type , adapter );
133+ }
134+ return builder .create ();
135+ }
136+
90137 // deals with scenario where gson Object type treats all numbers as doubles.
91- @ Provides TypeAdapter < Map < String , Object >> doubleToInt () {
138+ @ Provides ( type = Provides . Type . SET ) TypeAdapter doubleToInt () {
92139 return new TypeAdapter <Map <String , Object >>() {
93140 TypeAdapter <Map <String , Object >> delegate = new MapTypeAdapterFactory (new ConstructorConstructor (
94141 Collections .<Type , InstanceCreator <?>>emptyMap ()), false ).create (new Gson (), token );
@@ -111,10 +158,6 @@ public Map<String, Object> read(JsonReader in) throws IOException {
111158 }.nullSafe ();
112159 }
113160
114- @ Provides @ Singleton Gson gson (TypeAdapter <Map <String , Object >> doubleToInt ) {
115- return new GsonBuilder ().registerTypeAdapter (token .getType (), doubleToInt ).setPrettyPrinting ().create ();
116- }
117-
118- protected final static TypeToken <Map <String , Object >> token = new TypeToken <Map <String , Object >>() {
161+ private final static TypeToken <Map <String , Object >> token = new TypeToken <Map <String , Object >>() {
119162 };
120163}
0 commit comments