blob: 349737ad866e968e0e1562b1d4de85817e22b825 [file] [log] [blame]
Stuart McCullochf3173222012-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 {
Stuart McCulloch4482c702012-06-15 13:27:53 +00008 final Class< ? > rawClass;
9 final Type keyType;
10 final Type valueType;
Stuart McCullochf3173222012-06-07 21:57:32 +000011
Stuart McCulloch4482c702012-06-15 13:27:53 +000012 MapHandler(Class< ? > rawClass, Type keyType, Type valueType) {
Stuart McCullochf3173222012-06-07 21:57:32 +000013 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
Stuart McCulloch4482c702012-06-15 13:27:53 +000030 @Override
31 void encode(Encoder app, Object object, Map<Object,Type> visited) throws IOException, Exception {
32 Map< ? , ? > map = (Map< ? , ? >) object;
Stuart McCullochf3173222012-06-07 21:57:32 +000033
34 app.append("{");
35 String del = "";
Stuart McCulloch4482c702012-06-15 13:27:53 +000036 for (Map.Entry< ? , ? > e : map.entrySet()) {
Stuart McCullochf3173222012-06-07 21:57:32 +000037 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
Stuart McCulloch4482c702012-06-15 13:27:53 +000052 @Override
53 Object decodeObject(Decoder r) throws Exception {
Stuart McCullochf3173222012-06-07 21:57:32 +000054 assert r.current() == '{';
Stuart McCulloch4482c702012-06-15 13:27:53 +000055
56 Map<Object,Object> map = (Map<Object,Object>) rawClass.newInstance();
57
Stuart McCullochf3173222012-06-07 21:57:32 +000058 int c = r.next();
59 while (JSONCodec.START_CHARACTERS.indexOf(c) >= 0) {
60 Object key = r.codec.parseString(r);
Stuart McCulloch4482c702012-06-15 13:27:53 +000061 if (!(keyType == null || keyType == Object.class)) {
Stuart McCullochf3173222012-06-07 21:57:32 +000062 Handler h = r.codec.getHandler(keyType);
Stuart McCulloch4482c702012-06-15 13:27:53 +000063 key = h.decode((String) key);
Stuart McCullochf3173222012-06-07 21:57:32 +000064 }
Stuart McCulloch4482c702012-06-15 13:27:53 +000065
Stuart McCullochf3173222012-06-07 21:57:32 +000066 c = r.skipWs();
Stuart McCulloch4482c702012-06-15 13:27:53 +000067 if (c != ':')
Stuart McCullochf3173222012-06-07 21:57:32 +000068 throw new IllegalArgumentException("Expected ':' but got " + (char) c);
69
70 c = r.next();
71 Object value = r.codec.decode(valueType, r);
Stuart McCulloch4482c702012-06-15 13:27:53 +000072 if (value != null || !r.codec.ignorenull)
Stuart McCulloch0b639c62012-06-12 12:41:16 +000073 map.put(key, value);
Stuart McCullochf3173222012-06-07 21:57:32 +000074
75 c = r.skipWs();
Stuart McCulloch4482c702012-06-15 13:27:53 +000076
77 if (c == '}')
Stuart McCullochf3173222012-06-07 21:57:32 +000078 break;
79
80 if (c == ',') {
81 c = r.next();
82 continue;
83 }
84
Stuart McCulloch4482c702012-06-15 13:27:53 +000085 throw new IllegalArgumentException("Invalid character in parsing list, expected } or , but found "
86 + (char) c);
Stuart McCullochf3173222012-06-07 21:57:32 +000087 }
88 assert r.current() == '}';
89 r.read(); // skip closing
90 return map;
91 }
92
93}