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