blob: 5a413b6cbcd15d77163463f5542bd6fd90c0a413 [file] [log] [blame]
Stuart McCullochbb014372012-06-07 21:57:32 +00001package aQute.lib.json;
2
3import java.io.*;
4import java.lang.reflect.*;
5import java.util.*;
6
7public class MapHandler extends Handler {
8 final Class<?> rawClass;
9 final Type keyType;
10 final Type valueType;
11
12 MapHandler(Class<?> rawClass, Type keyType, Type valueType) {
13 this.keyType = keyType;
14 this.valueType = valueType;
15 if (rawClass.isInterface()) {
16 if (rawClass.isAssignableFrom(HashMap.class))
17 rawClass = HashMap.class;
18 else if (rawClass.isAssignableFrom(TreeMap.class))
19 rawClass = TreeMap.class;
20 else if (rawClass.isAssignableFrom(Hashtable.class))
21 rawClass = Hashtable.class;
22 else if (rawClass.isAssignableFrom(LinkedHashMap.class))
23 rawClass = LinkedHashMap.class;
24 else
25 throw new IllegalArgumentException("Unknown map interface: " + rawClass);
26 }
27 this.rawClass = rawClass;
28 }
29
30 @Override void encode(Encoder app, Object object, Map<Object, Type> visited)
31 throws IOException, Exception {
32 Map<?, ?> map = (Map<?, ?>) object;
33
34 app.append("{");
35 String del = "";
36 for (Map.Entry<?, ?> e : map.entrySet()) {
37 app.append(del);
38 String key;
39 if (e.getKey() != null && (keyType == String.class || keyType == Object.class))
40 key = e.getKey().toString();
41 else {
42 key = app.codec.enc().put(e.getKey()).toString();
43 }
44 StringHandler.string(app, key);
45 app.append(":");
46 app.encode(e.getValue(), valueType, visited);
47 del = ",";
48 }
49 app.append("}");
50 }
51
52 @SuppressWarnings("unchecked") @Override Object decodeObject(Decoder r) throws Exception {
53 assert r.current() == '{';
54
55 Map<Object, Object> map = (Map<Object, Object>) rawClass.newInstance();
56
57 int c = r.next();
58 while (JSONCodec.START_CHARACTERS.indexOf(c) >= 0) {
59 Object key = r.codec.parseString(r);
60 if ( !(keyType == null || keyType == Object.class)) {
61 Handler h = r.codec.getHandler(keyType);
62 key = h.decode((String)key);
63 }
64
65 c = r.skipWs();
66 if ( c != ':')
67 throw new IllegalArgumentException("Expected ':' but got " + (char) c);
68
69 c = r.next();
70 Object value = r.codec.decode(valueType, r);
71 map.put(key, value);
72
73 c = r.skipWs();
74
75 if (c == '}')
76 break;
77
78 if (c == ',') {
79 c = r.next();
80 continue;
81 }
82
83 throw new IllegalArgumentException(
84 "Invalid character in parsing list, expected } or , but found " + (char) c);
85 }
86 assert r.current() == '}';
87 r.read(); // skip closing
88 return map;
89 }
90
91}