fixed some doc strings. added sample makefile
[OpenSRF.git] / src / java / org / opensrf / util / JSONReader.java
1 package org.opensrf.util;
2
3 import java.io.*;
4 import java.util.*;
5
6 import org.json.JSONTokener;
7 import org.json.JSONObject;
8 import org.json.JSONArray;
9
10
11 /**
12  * JSON utilities.
13  */
14 public class JSONReader {
15
16     /** Special OpenSRF serializable object netClass key */
17     public static final String JSON_CLASS_KEY = "__c";
18
19     /** Special OpenSRF serializable object payload key */
20     public static final String JSON_PAYLOAD_KEY = "__p";
21
22     /** The JSON string to parser */
23     private String json;
24
25     /**
26      * @param json The JSON to parse
27      */
28     public JSONReader(String json) {
29         this.json = json;
30     }
31
32     /**
33      * Parses JSON and creates an object.
34      * @return The resulting object which may be a List, 
35      * Map, Number, String, Boolean, or null
36      */
37     public Object read() throws JSONException {
38         JSONTokener tk = new JSONTokener(json);
39         try {
40             return readSubObject(tk.nextValue());
41         } catch(org.json.JSONException e) {
42             throw new JSONException(e.toString());
43         }
44     }
45
46     /**
47      * Assumes that a JSON array will be read.  Returns
48      * the resulting array as a list.
49      */
50     public List<?> readArray() throws JSONException {
51         Object o = read();
52         try {
53             return (List<?>) o;
54         } catch(Exception e) {
55             throw new JSONException("readArray(): JSON cast exception");
56         }
57     }
58
59     /**
60      * Assumes that a JSON object will be read.  Returns 
61      * the resulting object as a map.
62      */
63     public Map<?,?> readObject() throws JSONException {
64         Object o = read();
65         try {
66             return (Map<?,?>) o;
67         } catch(Exception e) {
68             throw new JSONException("readObject(): JSON cast exception");
69         }
70     }
71
72
73     /**
74      * Recurse through the object and turn items into maps, lists, etc.
75      */
76     private Object readSubObject(Object obj) throws JSONException {
77
78         if( obj == null || 
79             obj instanceof String || 
80             obj instanceof Number ||
81             obj instanceof Boolean)
82                 return obj;
83
84         try {
85
86             if( obj instanceof JSONObject ) {
87
88                 /* read objects */
89                 String key;
90                 JSONObject jobj = (JSONObject) obj;
91                 Map<String, Object> map = new HashMap<String, Object>();
92
93                 for( Iterator e = jobj.keys(); e.hasNext(); ) {
94                     key = (String) e.next();
95
96                     /* we encoutered the special class key */
97                     if( JSON_CLASS_KEY.equals(key) ) 
98                         return buildRegisteredObject(
99                             (String) jobj.get(key), jobj.get(JSON_PAYLOAD_KEY));
100
101                     /* we encountered the data key */
102                     if( JSON_PAYLOAD_KEY.equals(key) ) 
103                         return buildRegisteredObject(
104                             (String) jobj.get(JSON_CLASS_KEY), jobj.get(key));
105
106                     map.put(key, readSubObject(jobj.get(key)));
107                 }
108                 return map;
109             } 
110             
111             if ( obj instanceof JSONArray ) {
112
113                 JSONArray jarr = (JSONArray) obj;
114                 int length = jarr.length();
115                 List<Object> list = new ArrayList<Object>(length);
116
117                 for( int i = 0; i < length; i++ ) 
118                     list.add(readSubObject(jarr.get(i)));   
119                 return list;
120                 
121             }
122
123         } catch(org.json.JSONException e) {
124
125             throw new JSONException(e.toString());
126         }
127
128         return null;
129     }
130
131
132
133     /**
134      * Builds an OSRFObject map registered OSRFHash object based on the JSON object data.
135      * @param netClass The network class hint for this object.
136      * @param paylaod The actual object on the wire.
137      */
138     private OSRFObject buildRegisteredObject(
139         String netClass, Object payload) throws JSONException {
140
141         OSRFRegistry registry = OSRFRegistry.getRegistry(netClass);
142         OSRFObject obj = new OSRFObject(registry);
143
144         try {
145             if( payload instanceof JSONArray ) {
146                 JSONArray jarr = (JSONArray) payload;
147
148                 /* for each array item, instert the item into the hash.  the hash 
149                  * key is found by extracting the fields array from the registered 
150                  * object at the current array index */
151                 String fields[] = registry.getFields();
152                 for( int i = 0; i < jarr.length(); i++ ) {
153                     obj.put(fields[i], readSubObject(jarr.get(i)));   
154                 }
155
156             } else if( payload instanceof JSONObject ) {
157
158                 /* since this is a hash, simply copy the data over */
159                 JSONObject jobj = (JSONObject) payload;
160                 String key;
161                 for( Iterator e = jobj.keys(); e.hasNext(); ) {
162                     key = (String) e.next();
163                     obj.put(key, readSubObject(jobj.get(key)));
164                 }
165             }
166
167         } catch(org.json.JSONException e) {
168             throw new JSONException(e.toString());
169         }
170
171         return obj;
172     }
173 }
174
175
176