1 package json;
2 
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.LinkedHashMap;
6 import java.util.Map.Entry;
7 
8 import structures.ByteBuilder;
9 
10 public class JsonObject {
11 
main(String[] args)12 	public static void main(String[] args){
13 		JsonObject bob=new JsonObject("name", "bob");
14 		JsonObject joe=new JsonObject("name", "joe");
15 		JsonObject sue=new JsonObject("name", "sue");
16 		JsonObject dan=new JsonObject("name", "dan");
17 		bob.add("joe", joe, true);
18 		bob.add("sue", sue, true);
19 		joe.add("dan", dan, true);
20 		bob.add("a",1, true);
21 		bob.add("b",2, true);
22 		bob.add("c","3", true);
23 		bob.add("a","4", true);
24 		dan.add("e",5, true);
25 		dan.add("f","6", true);
26 		sue.add("g","7", true);
27 
28 		System.out.println("dan:\n"+dan);
29 		System.out.println("sue:\n"+sue);
30 		System.out.println("joe:\n"+joe);
31 		System.out.println("bob:\n"+bob);
32 
33 		ArrayList<JsonObject> list=new ArrayList<JsonObject>();
34 		list.add(joe);
35 		list.add(sue);
36 		list.add(dan);
37 		System.out.println("list:\n"+toString(list));
38 	}
39 
JsonObject()40 	public JsonObject(){}
41 
JsonObject(String key, Object value)42 	public JsonObject(String key, Object value){
43 		add(key, value, true);
44 	}
45 
46 //	public JsonObject(String name_){
47 //		name=name_;
48 //	}
49 //
50 //	public JsonObject(String name_, String key, Object value){
51 //		name=name_;
52 //		add(key, value);
53 //	}
54 
55 	/** Adds a formatted value with specified decimal places */
addLiteral(String key0, double value, int decimals)56 	public void addLiteral(String key0, double value, int decimals){
57 		if(omap==null){omap=new LinkedHashMap<String, Object>(8);}
58 		omap.put(key0, new JsonLiteral(value, decimals));
59 	}
60 
61 	/** Does not add quotes for strings.
62 	 * This method should be used with caution as it can produce incorrectly formatted files. */
addLiteral(String key0, String value)63 	public void addLiteral(String key0, String value){
64 		if(omap==null){omap=new LinkedHashMap<String, Object>(8);}
65 		omap.put(key0, new JsonLiteral(value));
66 	}
67 
add(String key0, Object value)68 	public void add(String key0, Object value){add(key0, value, true);}
addAndRename(String key0, Object value)69 	public void addAndRename(String key0, Object value){add(key0, value, false);}
70 
add(String key0, Object value, boolean replace)71 	private void add(String key0, Object value, boolean replace){
72 		if(value!=null && value.getClass()==JsonObject.class){
73 			add(key0, (JsonObject)value, replace);
74 			return;
75 		}
76 		int x=2;
77 		String key=key0;
78 		if(omap==null){omap=new LinkedHashMap<String, Object>(8);}
79 		while(!replace && omap.containsKey(key)){
80 			key=key0+" "+x;
81 			x++;
82 		}
83 		omap.put(key, value);
84 	}
85 
add(String key0, JsonObject value)86 	public void add(String key0, JsonObject value){add(key0, value, true);}
addAndRename(String key0, JsonObject value)87 	public void addAndRename(String key0, JsonObject value){add(key0, value, false);}
88 
add(final String key0, JsonObject value, boolean replace)89 	private void add(final String key0, JsonObject value, boolean replace){
90 		int x=2;
91 		String key=key0;
92 		if(jmap==null){jmap=new LinkedHashMap<String, JsonObject>(8);}
93 		while(!replace && jmap.containsKey(key)){
94 			key=key0+" "+x;
95 			x++;
96 		}
97 		jmap.put(key, value);
98 	}
99 
toString(ArrayList<JsonObject> list)100 	public static String toString(ArrayList<JsonObject> list) {
101 		ByteBuilder sb=new ByteBuilder();
102 		int commas=list.size()-1;
103 		for(JsonObject j : list){
104 			j.append(0, sb, false);
105 			if(commas>0){
106 				sb.append(",\n");
107 			}
108 			commas--;
109 		}
110 		return sb.toString();
111 	}
112 
toText()113 	public ByteBuilder toText(){
114 		return toText(null, 0, false);
115 	}
116 
toText(ByteBuilder sb, int level, boolean inArray)117 	public ByteBuilder toText(ByteBuilder sb, int level, boolean inArray){
118 		if(sb==null){sb=new ByteBuilder();}
119 		append(level, sb, inArray);
120 		return sb;
121 	}
122 
toString(String name)123 	public String toString(String name){
124 		ByteBuilder sb=new ByteBuilder();
125 		sb.append('{').append('\n');
126 		for(int i=0; i<padmult; i++){sb.append(' ');}
127 		sb.append('"').append(name).append('"').append(':').append(' ');
128 		toText(sb, 1, false);
129 		sb.append('\n').append('}');
130 		return sb.toString();
131 	}
132 
toString(Object[] array)133 	public static String toString(Object[] array){
134 		ByteBuilder sb=new ByteBuilder();
135 		appendArray(sb, array, 0);
136 		return sb.toString();
137 	}
138 
139 	@Override
toString()140 	public String toString(){
141 		return toText(null, 0, false).toString();
142 	}
143 
toStringln()144 	public String toStringln(){
145 		return toText(null, 0, false).nl().toString();
146 	}
147 
append(int level, ByteBuilder sb, boolean inArray)148 	public void append(int level, ByteBuilder sb, boolean inArray){
149 		int pad=padmult*level;
150 		int pad2=padmult*(level+1);
151 
152 		sb.append('{');
153 		if(!inArray){sb.append('\n');}
154 
155 		int commas=(omap==null ? 0 : omap.size())+(jmap==null ? 0 : jmap.size())-1;
156 
157 		if(omap!=null){
158 			for(Entry<String, Object> e : omap.entrySet()){
159 				String key=e.getKey();
160 				Object value=e.getValue();
161 				if(!inArray){for(int i=0; i<pad2; i++){sb.append(' ');}}
162 
163 				appendEntry(sb, key, value, level, inArray);
164 
165 				if(commas>0){sb.append(',');}
166 				if(!inArray){sb.append('\n');}
167 				commas--;
168 			}
169 		}
170 
171 		if(jmap!=null){
172 			for(Entry<String, JsonObject> e : jmap.entrySet()){
173 				String key=e.getKey();
174 				JsonObject value=e.getValue();
175 				if(!inArray){for(int i=0; i<pad2; i++){sb.append(' ');}}
176 				appendKey(sb, key);
177 
178 				value.append(level+(inArray ? 0 : 1), sb, inArray);
179 				if(commas>0){sb.append(',');}
180 				if(!inArray){sb.append('\n');}
181 				commas--;
182 			}
183 		}
184 
185 		if(!inArray){for(int i=0; i<pad; i++){sb.append(' ');}}
186 		sb.append('}');
187 	}
188 
appendEntry(ByteBuilder sb, String key, Object value, int level, boolean inArray)189 	private static void appendEntry(ByteBuilder sb, String key, Object value, int level, boolean inArray){
190 		appendKey(sb, key);
191 		appendValue(sb, value, level, inArray);
192 	}
193 
appendKey(ByteBuilder sb, String key)194 	private static void appendKey(ByteBuilder sb, String key){
195 		sb.append('"').append(key).append("\": ");
196 	}
197 
appendValue(ByteBuilder sb, Object value, int level, boolean inArray)198 	private static void appendValue(ByteBuilder sb, Object value, int level, boolean inArray){
199 		final Class<?> c=(value==null ? null : value.getClass());
200 		if(c==null || value==null){
201 			sb.append("null");
202 		}else if(c==String.class){
203 			sb.append("\"").append(value.toString()).append('"');
204 		}else if(c==JsonLiteral.class){
205 			sb.append(((JsonLiteral)value).toString());
206 		}else if(c==Double.class && restictDecimals>=0){
207 			sb.append(((Double)value).doubleValue(), restictDecimals);
208 		}else if(c==Float.class && restictDecimals>=0){
209 			sb.append(((Float)value).floatValue(), restictDecimals);
210 		}else if(c==JsonObject.class){
211 			((JsonObject)value).append(level+(inArray ? 0 : 1), sb, inArray);
212 		}else if(c.isArray()){
213 			appendArray(sb, (Object[])value, level);
214 		}else if(c==Boolean.class || value instanceof Number){//long, int, boolean
215 			sb.append(value.toString());
216 		}else if(value instanceof Collection){
217 			appendCollection(sb, (Collection<?>)value, level);
218 		}else{//Default behavior for unhandled classes
219 			sb.append("\"").append(value.toString()).append('"');
220 		}
221 	}
222 
appendArray(ByteBuilder sb, Object[] array, int level)223 	private static void appendArray(ByteBuilder sb, Object[] array, int level){
224 		int commas=(array==null ? 0 : array.length)-1;
225 		sb.append('[');
226 		if(array!=null){
227 			for(Object value : array){
228 				appendValue(sb, value, level, noNewlinesInArrays);
229 				if(commas>0){sb.append(',').append(' ');}
230 				commas--;
231 			}
232 		}
233 		sb.append(']');
234 	}
235 
appendCollection(ByteBuilder sb, Collection<?> stuff, int level)236 	private static void appendCollection(ByteBuilder sb, Collection<?> stuff, int level){
237 		int commas=(stuff==null ? 0 : stuff.size())-1;
238 		sb.append('[');
239 		if(stuff!=null){
240 			for(Object value : stuff){
241 				appendValue(sb, value, level, noNewlinesInArrays);
242 				if(commas>0){sb.append(',').append(' ');}
243 				commas--;
244 			}
245 		}
246 		sb.append(']');
247 	}
248 
getString(String key)249 	public String getString(String key){
250 		if(omap==null){return null;}
251 		Object o=omap.get(key);
252 		if(o==null){return null;}
253 		assert(o.getClass()==String.class) : "Wrong class: "+o.getClass()+"\n"+o;
254 		return (String)o;
255 	}
256 
getLong(String key)257 	public Long getLong(String key){
258 		if(omap==null){return null;}
259 		Object o=omap.get(key);
260 		if(o==null){return null;}
261 		assert(o.getClass()==Long.class) : "Wrong class: "+o.getClass()+"\n"+o;
262 		return (Long)o;
263 	}
264 
getInt(String key)265 	public Integer getInt(String key){
266 		assert(omap!=null);
267 		Object o=omap.get(key);
268 //		assert(o!=null);
269 		assert(o==null || o.getClass()==Integer.class) : "Wrong class: "+o.getClass()+"\n"+o;
270 //		long x=((Long)o).longValue();
271 //		assert(x>=Integer.MIN_VALUE && x<=Integer.MAX_VALUE);
272 //		return (int)x;
273 		return (Integer)o;
274 	}
275 
containsKey(String key)276 	public boolean containsKey(String key){
277 		if(omap!=null && omap.containsKey(key)){return true;}
278 		if(jmap!=null && jmap.containsKey(key)){return true;}
279 		return false;
280 	}
281 
282 //	public Double getDouble(String key){
283 //		if(smap==null){return null;}
284 //		Object o=smap.get(key);
285 //		if(o==null){return null;}
286 //		assert(o.getClass()==Double.class) : "Wrong class: "+o.getClass()+"\n"+o;
287 //		return (Double)o;
288 //	}
289 
getDouble(String key)290 	public Double getDouble(String key){
291 		if(omap==null){return null;}
292 		Object o=omap.get(key);
293 		if(o==null){return null;}
294 		if(o.getClass()==Long.class){
295 			return ((Long)o).doubleValue();
296 		}
297 		assert(o.getClass()==Double.class) : "Wrong class: "+o.getClass()+"\n"+o;
298 		return (Double)o;
299 	}
300 
getNumber(String key)301 	public Number getNumber(String key){
302 		if(omap==null){return null;}
303 		Object o=omap.get(key);
304 		if(o==null){return null;}
305 		Class<?> c=o.getClass();
306 		assert(c==Double.class || c==Long.class || c==Integer.class || c==Float.class) : "Wrong class: "+c+"\n"+o;
307 		return (Number)o;
308 	}
309 
getArray(String key)310 	public Object[] getArray(String key){
311 		if(omap==null){return null;}
312 		Object o=omap.get(key);
313 		if(o==null){return null;}
314 		assert(o.getClass()==Object[].class) : "Wrong class: "+o.getClass()+"\n"+o;
315 		return (Object[])o;
316 	}
317 
getJson(String key)318 	public JsonObject getJson(String key){
319 		if(jmap==null){return null;}
320 		return jmap.get(key);
321 	}
322 
removeJson(String key)323 	public JsonObject removeJson(String key){
324 		if(jmap==null){return null;}
325 		return jmap.remove(key);
326 	}
327 
removeObject(String key)328 	public Object removeObject(String key){
329 		if(omap==null){return null;}
330 		return omap.remove(key);
331 	}
332 
clearJson()333 	public void clearJson(){
334 		jmap=null;
335 	}
336 
clearOmap()337 	public void clearOmap(){
338 		omap=null;
339 	}
340 
toJmapArray()341 	public Object[] toJmapArray() {
342 		if(jmap==null){return null;}
343 		Object[] array=new Object[jmapSize()];
344 		int i=0;
345 		for(Entry<String, JsonObject> e : jmap.entrySet()){
346 			array[i]=e.getValue();
347 			i++;
348 		}
349 		return array;
350 	}
351 
jmapSize()352 	public int jmapSize(){return jmap==null ? 0 : jmap.size();}
omapSize()353 	public int omapSize(){return omap==null ? 0 : omap.size();}
354 
355 //	public String name;
356 	public LinkedHashMap<String, Object> omap;
357 	public LinkedHashMap<String, JsonObject> jmap;
358 
359 	private static int restictDecimals=-1;
360 	private static String decimalFormat="%."+restictDecimals+"f";
setDecimals(int d)361 	public static synchronized void setDecimals(int d){
362 		if(d!=restictDecimals){
363 			d=restictDecimals;
364 			decimalFormat="%."+restictDecimals+"f";
365 		}
366 	}
367 
368 	public static final int padmult=3;
369 	public static boolean noNewlinesInArrays=false;
370 
371 }
372