blob: 929987807d82dfe1f23d8c36e4fc4de2f1a930ce [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);
Stuart McCulloch285034f2012-06-12 12:41:16 +000071 if ( value != null || !r.codec.ignorenull)
72 map.put(key, value);
Stuart McCullochbb014372012-06-07 21:57:32 +000073
74 c = r.skipWs();
75
76 if (c == '}')
77 break;
78
79 if (c == ',') {
80 c = r.next();
81 continue;
82 }
83
84 throw new IllegalArgumentException(
85 "Invalid character in parsing list, expected } or , but found " + (char) c);
86 }
87 assert r.current() == '}';
88 r.read(); // skip closing
89 return map;
90 }
91
92}