1 package org.apache.struts.flow.json;
2
3
4 import java.util.ArrayList;
5 import java.util.Collection;
6 import java.util.Iterator;
7 import java.util.Locale;
8 import java.util.Map;
9 import java.util.*;
10
11 import java.text.ParseException;
12 import org.apache.commons.logging.*;
13
14 import java.beans.BeanInfo;
15 import java.beans.Introspector;
16 import java.beans.PropertyDescriptor;
17 import java.lang.reflect.Array;
18 import java.lang.reflect.Method;
19
20 /***
21 * Serializes objects into JSON
22 */
23 public class JSONSerializer {
24
25 private static final Hashtable propDescs = new Hashtable();
26
27 private Properties varLookup = new Properties();
28 private final static Log log = LogFactory.getLog(JSONSerializer.class);
29
30 public void setVariableLookupTable(Properties props) {
31 this.varLookup = props;
32 Map.Entry entry;
33 Map map = new HashMap();
34 for (Iterator i = props.entrySet().iterator(); i.hasNext(); ) {
35 entry = (Map.Entry)i.next();
36 map.put(entry.getValue(), entry.getKey());
37 }
38 props.putAll(map);
39 }
40
41 public String serialize(Object bean) {
42 Object o = serialize(bean, null, null, new ArrayList());
43 if (o != null) {
44 return o.toString();
45 }
46 return null;
47 }
48
49 /***
50 * Recursive function to serialize objects to JSON objects that will
51 * handle serialization into JSON. Currently it will
52 * serialize Collections, Maps, Arrays, and javabeans. It maintains a
53 * stack of objects serialized already in the
54 * current functioncall. This is used to avoid looping (stack overflow) of
55 * circular linked objects.
56 *
57 *@param bean The object you want serialized.
58 *@param name The name of the object, used for element
59 * <name/>
60 *@param handler XMLConsumer
61 *@param stack Vector of objects we're serializing since the
62 * first calling of this function (to prevent looping on circular
63 * references).
64 *@exception SAXException If something goes wrong
65 */
66 private Object serialize(Object bean, String name, Object parent, List stack) {
67
68
69
70
71
72
73
74
75 if (bean != null) {
76
77
78 stack.add(bean);
79 } else {
80
81 return null;
82 }
83 String clsName = bean.getClass().getName();
84 Object jsonobject = null;
85
86
87 if (bean instanceof Map) {
88
89 Map map = (Map) bean;
90 JSONObject object = createObject(parent, name);
91
92
93 for (Iterator i = map.keySet().iterator(); i.hasNext(); ) {
94 Object key = i.next();
95 Object Objvalue = map.get(key);
96
97 serialize(Objvalue, key.toString(), object, stack);
98 }
99 jsonobject = object;
100 } else if (bean instanceof Collection) {
101 Collection col = (Collection) bean;
102
103 JSONArray array = createArray(parent, name);
104
105 for (Iterator i = col.iterator(); i.hasNext(); ) {
106 serialize(i.next(), null, array, stack);
107 }
108 jsonobject = array;
109 } else if (bean.getClass().isArray()) {
110 JSONArray array = createArray(parent, name);
111
112 for (int i = 0; i < Array.getLength(bean); i++) {
113 serialize(Array.get(bean, i), null, array, stack);
114 }
115 jsonobject = array;
116 }
117 else if (clsName.startsWith("java.lang")) {
118 String val = bean.toString();
119 if (parent != null) {
120 if (name == null) {
121 ((JSONArray)parent).put(val);
122 } else {
123 name = varLookup.getProperty(name, name);
124 ((JSONObject)parent).put(name, val);
125 }
126 }
127 jsonobject = val;
128 } else {
129
130 try {
131 PropertyDescriptor[] props = (PropertyDescriptor[])propDescs.get(bean.getClass());
132 if (props == null) {
133 BeanInfo info = Introspector.getBeanInfo(bean.getClass());
134 props = info.getPropertyDescriptors();
135 propDescs.put(bean.getClass(), props);
136 }
137 JSONObject object = createObject(parent, name);
138
139
140 for (int i = 0; i < props.length; i++) {
141 Class t = props[i].getPropertyType();
142 String n = props[i].getName();
143 Method m = props[i].getReadMethod();
144
145
146
147
148 if (m != null && !m.getName().equals("getClass")) {
149 serialize(m.invoke(bean, null), n, object, stack);
150 }
151 }
152 jsonobject = object;
153 }
154 catch (Exception e) {
155
156 e.printStackTrace();
157
158 }
159 }
160
161
162 stack.remove(bean);
163 return jsonobject;
164 }
165
166 private JSONArray createArray(Object parent, String name) {
167 JSONArray array = new JSONArray();
168 if (parent != null) {
169 if (parent instanceof JSONArray) {
170 ((JSONArray)parent).put(array);
171 } else {
172 name = varLookup.getProperty(name, name);
173 ((JSONObject)parent).put(name, array);
174 }
175 }
176 return array;
177 }
178
179 private JSONObject createObject(Object parent, String name) {
180 JSONObject array = new JSONObject();
181 if (parent != null) {
182 if (parent instanceof JSONArray) {
183 ((JSONArray)parent).put(array);
184 } else {
185 name = varLookup.getProperty(name, name);
186 ((JSONObject)parent).put(name, array);
187 }
188 }
189 return array;
190 }
191
192 }
193