JAL-3438 spotless for 2.11.2.0
[jalview.git] / src / org / json / simple / JSONValue.java
1 /*
2  * $Id: JSONValue.java,v 1.1 2006/04/15 14:37:04 platform Exp $
3  * Created on 2006-4-15
4  */
5 package org.json.simple;
6
7 import java.io.IOException;
8 import java.io.Reader;
9 import java.io.StringReader;
10 import java.io.StringWriter;
11 import java.io.Writer;
12 import java.util.Collection;
13 import java.util.Locale;
14 // import java.util.List;
15 import java.util.Map;
16
17 import org.json.simple.parser.JSONParser;
18 import org.json.simple.parser.ParseException;
19
20 /**
21  * @author FangYidong<fangyidong@yahoo.com.cn>
22  */
23 public class JSONValue
24 {
25   /**
26    * Parse JSON text into java object from the input source. Please use
27    * parseWithException() if you don't want to ignore the exception.
28    * 
29    * @see org.json.simple.parser.JSONParser#parse(Reader)
30    * @see #parseWithException(Reader)
31    * 
32    * @param in
33    * @return Instance of the following: org.json.simple.JSONObject,
34    *         org.json.simple.JSONArray, java.lang.String, java.lang.Number,
35    *         java.lang.Boolean, null
36    * 
37    * @deprecated this method may throw an {@code Error} instead of returning
38    *             {@code null}; please use
39    *             {@link JSONValue#parseWithException(Reader)} instead
40    */
41   @Deprecated
42   public static Object parse(Reader in)
43   {
44     try
45     {
46       JSONParser parser = new JSONParser();
47       return parser.parse(in);
48     } catch (Exception e)
49     {
50       return null;
51     }
52   }
53
54   /**
55    * Parse JSON text into java object from the given string. Please use
56    * parseWithException() if you don't want to ignore the exception.
57    * 
58    * @see org.json.simple.parser.JSONParser#parse(Reader)
59    * @see #parseWithException(Reader)
60    * 
61    * @param s
62    * @return Instance of the following: org.json.simple.JSONObject,
63    *         org.json.simple.JSONArray, java.lang.String, java.lang.Number,
64    *         java.lang.Boolean, null
65    * 
66    * @deprecated this method may throw an {@code Error} instead of returning
67    *             {@code null}; please use
68    *             {@link JSONValue#parseWithException(String)} instead
69    */
70   @Deprecated
71   public static Object parse(String s)
72   {
73     StringReader in = new StringReader(s);
74     return parse(in);
75   }
76
77   /**
78    * Parse JSON text into java object from the input source.
79    * 
80    * @see org.json.simple.parser.JSONParser
81    * 
82    * @param in
83    * @return Instance of the following: org.json.simple.JSONObject,
84    *         org.json.simple.JSONArray, java.lang.String, java.lang.Number,
85    *         java.lang.Boolean, null
86    * 
87    * @throws IOException
88    * @throws ParseException
89    */
90   public static Object parseWithException(Reader in)
91           throws IOException, ParseException
92   {
93     JSONParser parser = new JSONParser();
94     return parser.parse(in);
95   }
96
97   public static Object parseWithException(String s) throws ParseException
98   {
99     JSONParser parser = new JSONParser();
100     return parser.parse(s);
101   }
102
103   /**
104    * Encode an object into JSON text and write it to out.
105    * <p>
106    * If this object is a Map or a List, and it's also a JSONStreamAware or a
107    * JSONAware, JSONStreamAware or JSONAware will be considered firstly.
108    * <p>
109    * DO NOT call this method from writeJSONString(Writer) of a class that
110    * implements both JSONStreamAware and (Map or List) with "this" as the first
111    * parameter, use JSONObject.writeJSONString(Map, Writer) or
112    * JSONArray.writeJSONString(List, Writer) instead.
113    * 
114    * @see org.json.simple.JSONObject#writeJSONString(Map, Writer)
115    * @see org.json.simple.JSONArray#writeJSONString(List, Writer)
116    * 
117    * @param value
118    * @param writer
119    */
120   public static void writeJSONString(Object value, Writer out)
121           throws IOException
122   {
123     if (value == null)
124     {
125       out.write("null");
126       return;
127     }
128
129     if (value instanceof String)
130     {
131       out.write('\"');
132       out.write(escape((String) value));
133       out.write('\"');
134       return;
135     }
136
137     if (value instanceof Double)
138     {
139       if (((Double) value).isInfinite() || ((Double) value).isNaN())
140         out.write("null");
141       else
142         out.write(value.toString());
143       return;
144     }
145
146     if (value instanceof Float)
147     {
148       if (((Float) value).isInfinite() || ((Float) value).isNaN())
149         out.write("null");
150       else
151         out.write(value.toString());
152       return;
153     }
154
155     if (value instanceof Number)
156     {
157       out.write(value.toString());
158       return;
159     }
160
161     if (value instanceof Boolean)
162     {
163       out.write(value.toString());
164       return;
165     }
166
167     if ((value instanceof JSONStreamAware))
168     {
169       ((JSONStreamAware) value).writeJSONString(out);
170       return;
171     }
172
173     if ((value instanceof JSONAware))
174     {
175       out.write(((JSONAware) value).toJSONString());
176       return;
177     }
178
179     if (value instanceof Map)
180     {
181       JSONObject.writeJSONString((Map) value, out);
182       return;
183     }
184
185     if (value instanceof Collection)
186     {
187       JSONArray.writeJSONString((Collection) value, out);
188       return;
189     }
190
191     if (value instanceof byte[])
192     {
193       JSONArray.writeJSONString((byte[]) value, out);
194       return;
195     }
196
197     if (value instanceof short[])
198     {
199       JSONArray.writeJSONString((short[]) value, out);
200       return;
201     }
202
203     if (value instanceof int[])
204     {
205       JSONArray.writeJSONString((int[]) value, out);
206       return;
207     }
208
209     if (value instanceof long[])
210     {
211       JSONArray.writeJSONString((long[]) value, out);
212       return;
213     }
214
215     if (value instanceof float[])
216     {
217       JSONArray.writeJSONString((float[]) value, out);
218       return;
219     }
220
221     if (value instanceof double[])
222     {
223       JSONArray.writeJSONString((double[]) value, out);
224       return;
225     }
226
227     if (value instanceof boolean[])
228     {
229       JSONArray.writeJSONString((boolean[]) value, out);
230       return;
231     }
232
233     if (value instanceof char[])
234     {
235       JSONArray.writeJSONString((char[]) value, out);
236       return;
237     }
238
239     if (value instanceof Object[])
240     {
241       JSONArray.writeJSONString((Object[]) value, out);
242       return;
243     }
244
245     out.write(value.toString());
246   }
247
248   /**
249    * Convert an object to JSON text.
250    * <p>
251    * If this object is a Map or a List, and it's also a JSONAware, JSONAware
252    * will be considered firstly.
253    * <p>
254    * DO NOT call this method from toJSONString() of a class that implements both
255    * JSONAware and Map or List with "this" as the parameter, use
256    * JSONObject.toJSONString(Map) or JSONArray.toJSONString(List) instead.
257    * 
258    * @see org.json.simple.JSONObject#toJSONString(Map)
259    * @see org.json.simple.JSONArray#toJSONString(List)
260    * 
261    * @param value
262    * @return JSON text, or "null" if value is null or it's an NaN or an INF
263    *         number.
264    */
265   public static String toJSONString(Object value)
266   {
267     final StringWriter writer = new StringWriter();
268
269     try
270     {
271       writeJSONString(value, writer);
272       return writer.toString();
273     } catch (IOException e)
274     {
275       // This should never happen for a StringWriter
276       throw new RuntimeException(e);
277     }
278   }
279
280   /**
281    * Escape quotes, \, /, \r, \n, \b, \f, \t and other control characters
282    * (U+0000 through U+001F).
283    * 
284    * @param s
285    * @return
286    */
287   public static String escape(String s)
288   {
289     if (s == null)
290       return null;
291     StringBuffer sb = new StringBuffer();
292     escape(s, sb);
293     return sb.toString();
294   }
295
296   /**
297    * @param s
298    *          - Must not be null.
299    * @param sb
300    */
301   static void escape(String s, StringBuffer sb)
302   {
303     final int len = s.length();
304     for (int i = 0; i < len; i++)
305     {
306       char ch = s.charAt(i);
307       switch (ch)
308       {
309       case '"':
310         sb.append("\\\"");
311         break;
312       case '\\':
313         sb.append("\\\\");
314         break;
315       case '\b':
316         sb.append("\\b");
317         break;
318       case '\f':
319         sb.append("\\f");
320         break;
321       case '\n':
322         sb.append("\\n");
323         break;
324       case '\r':
325         sb.append("\\r");
326         break;
327       case '\t':
328         sb.append("\\t");
329         break;
330       case '/':
331         sb.append("\\/");
332         break;
333       default:
334         // Reference: http://www.unicode.org/versions/Unicode5.1.0/
335         if ((ch >= '\u0000' && ch <= '\u001F')
336                 || (ch >= '\u007F' && ch <= '\u009F')
337                 || (ch >= '\u2000' && ch <= '\u20FF'))
338         {
339           String ss = Integer.toHexString(ch);
340           sb.append("\\u");
341           for (int k = 0; k < 4 - ss.length(); k++)
342           {
343             sb.append('0');
344           }
345           sb.append(ss.toUpperCase(Locale.ROOT));
346         }
347         else
348         {
349           sb.append(ch);
350         }
351       }
352     } // for
353   }
354
355 }