1
16 package com.squareup.moshi;
17
18 import java.io.IOException;
19 import java.lang.annotation.Annotation;
20 import java.lang.reflect.Type;
21 import java.util.Map;
22 import java.util.Set;
23 import javax.annotation.Nullable;
24
25
30 final class MapJsonAdapter<K, V> extends JsonAdapter<Map<K, V>> {
31 public static final Factory FACTORY = new Factory() {
32 @Override public @Nullable JsonAdapter<?> create(
33 Type type, Set<? extends Annotation> annotations, Moshi moshi) {
34 if (!annotations.isEmpty()) return null;
35 Class<?> rawType = Types.getRawType(type);
36 if (rawType != Map.class) return null;
37 Type[] keyAndValue = Types.mapKeyAndValueTypes(type, rawType);
38 return new MapJsonAdapter<>(moshi, keyAndValue[0], keyAndValue[1]).nullSafe();
39 }
40 };
41
42 private final JsonAdapter<K> keyAdapter;
43 private final JsonAdapter<V> valueAdapter;
44
45 MapJsonAdapter(Moshi moshi, Type keyType, Type valueType) {
46 this.keyAdapter = moshi.adapter(keyType);
47 this.valueAdapter = moshi.adapter(valueType);
48 }
49
50 @Override public void toJson(JsonWriter writer, Map<K, V> map) throws IOException {
51 writer.beginObject();
52 for (Map.Entry<K, V> entry : map.entrySet()) {
53 if (entry.getKey() == null) {
54 throw new JsonDataException("Map key is null at " + writer.getPath());
55 }
56 writer.promoteValueToName();
57 keyAdapter.toJson(writer, entry.getKey());
58 valueAdapter.toJson(writer, entry.getValue());
59 }
60 writer.endObject();
61 }
62
63 @Override public Map<K, V> fromJson(JsonReader reader) throws IOException {
64 LinkedHashTreeMap<K, V> result = new LinkedHashTreeMap<>();
65 reader.beginObject();
66 while (reader.hasNext()) {
67 reader.promoteNameToValue();
68 K name = keyAdapter.fromJson(reader);
69 V value = valueAdapter.fromJson(reader);
70 V replaced = result.put(name, value);
71 if (replaced != null) {
72 throw new JsonDataException("Map key '" + name + "' has multiple values at path "
73 + reader.getPath() + ": " + replaced + " and " + value);
74 }
75 }
76 reader.endObject();
77 return result;
78 }
79
80 @Override public String toString() {
81 return "JsonAdapter(" + keyAdapter + "=" + valueAdapter + ")";
82 }
83 }
84