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