blob: 62bf07fe96cfcab9c64dadfe75a57083097f6ad6 [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 {
Stuart McCulloch2286f232012-06-15 13:27:53 +00008 final Class< ? > rawClass;
9 final Type keyType;
10 final Type valueType;
Stuart McCullochbb014372012-06-07 21:57:32 +000011
Stuart McCulloch2286f232012-06-15 13:27:53 +000012 MapHandler(Class< ? > rawClass, Type keyType, Type valueType) {
Stuart McCullochbb014372012-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;
Stuart McCulloch81d48de2012-06-29 19:23:09 +000024 else if (rawClass.isAssignableFrom(Dictionary.class))
25 rawClass = Hashtable.class;
Stuart McCullochbb014372012-06-07 21:57:32 +000026 else
27 throw new IllegalArgumentException("Unknown map interface: " + rawClass);
28 }
29 this.rawClass = rawClass;
30 }
31
Stuart McCulloch2286f232012-06-15 13:27:53 +000032 @Override
33 void encode(Encoder app, Object object, Map<Object,Type> visited) throws IOException, Exception {
34 Map< ? , ? > map = (Map< ? , ? >) object;
Stuart McCullochbb014372012-06-07 21:57:32 +000035
36 app.append("{");
37 String del = "";
Stuart McCulloch2286f232012-06-15 13:27:53 +000038 for (Map.Entry< ? , ? > e : map.entrySet()) {
Stuart McCullochbb014372012-06-07 21:57:32 +000039 app.append(del);
40 String key;
41 if (e.getKey() != null && (keyType == String.class || keyType == Object.class))
42 key = e.getKey().toString();
43 else {
44 key = app.codec.enc().put(e.getKey()).toString();
45 }
46 StringHandler.string(app, key);
47 app.append(":");
48 app.encode(e.getValue(), valueType, visited);
49 del = ",";
50 }
51 app.append("}");
52 }
53
Stuart McCulloch2286f232012-06-15 13:27:53 +000054 @Override
55 Object decodeObject(Decoder r) throws Exception {
Stuart McCullochbb014372012-06-07 21:57:32 +000056 assert r.current() == '{';
Stuart McCulloch2286f232012-06-15 13:27:53 +000057
58 Map<Object,Object> map = (Map<Object,Object>) rawClass.newInstance();
59
Stuart McCullochbb014372012-06-07 21:57:32 +000060 int c = r.next();
61 while (JSONCodec.START_CHARACTERS.indexOf(c) >= 0) {
62 Object key = r.codec.parseString(r);
Stuart McCulloch2286f232012-06-15 13:27:53 +000063 if (!(keyType == null || keyType == Object.class)) {
Stuart McCullochbb014372012-06-07 21:57:32 +000064 Handler h = r.codec.getHandler(keyType);
Stuart McCulloch2286f232012-06-15 13:27:53 +000065 key = h.decode((String) key);
Stuart McCullochbb014372012-06-07 21:57:32 +000066 }
Stuart McCulloch2286f232012-06-15 13:27:53 +000067
Stuart McCullochbb014372012-06-07 21:57:32 +000068 c = r.skipWs();
Stuart McCulloch2286f232012-06-15 13:27:53 +000069 if (c != ':')
Stuart McCullochbb014372012-06-07 21:57:32 +000070 throw new IllegalArgumentException("Expected ':' but got " + (char) c);
71
72 c = r.next();
73 Object value = r.codec.decode(valueType, r);
Stuart McCulloch2286f232012-06-15 13:27:53 +000074 if (value != null || !r.codec.ignorenull)
Stuart McCulloch285034f2012-06-12 12:41:16 +000075 map.put(key, value);
Stuart McCullochbb014372012-06-07 21:57:32 +000076
77 c = r.skipWs();
Stuart McCulloch2286f232012-06-15 13:27:53 +000078
79 if (c == '}')
Stuart McCullochbb014372012-06-07 21:57:32 +000080 break;
81
82 if (c == ',') {
83 c = r.next();
84 continue;
85 }
86
Stuart McCulloch2286f232012-06-15 13:27:53 +000087 throw new IllegalArgumentException("Invalid character in parsing list, expected } or , but found "
88 + (char) c);
Stuart McCullochbb014372012-06-07 21:57:32 +000089 }
90 assert r.current() == '}';
91 r.read(); // skip closing
92 return map;
93 }
94
95}