001/* Copyright 2006 FangYidong
002
003   Licensed under the Apache License, Version 2.0 (the "License");
004   you may not use this file except in compliance with the License.
005   You may obtain a copy of the License at
006
007       http://www.apache.org/licenses/LICENSE-2.0
008
009   Unless required by applicable law or agreed to in writing, software
010   distributed under the License is distributed on an "AS IS" BASIS,
011   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012   See the License for the specific language governing permissions and
013   limitations under the License. */
014package org.json.simple;
015
016import java.io.IOException;
017import java.io.Reader;
018import java.io.StringReader;
019import java.io.StringWriter;
020import java.io.Writer;
021import java.util.Collection;
022// import java.util.List;
023import java.util.Map;
024
025import org.json.simple.parser.JSONParser;
026import org.json.simple.parser.ParseException;
027
028
029/**
030 * @author FangYidong<fangyidong@yahoo.com.cn>
031 * @deprecated since 2.0.0, replaced by {@link org.json.simple.Jsoner}
032 */
033@Deprecated
034public class JSONValue {
035        /**
036         * Parse JSON text into java object from the input source. 
037         * Please use parseWithException() if you don't want to ignore the exception.
038         * 
039         * @see org.json.simple.parser.JSONParser#parse(Reader)
040         * @see #parseWithException(Reader)
041         * 
042         * @param in description omitted.
043         * @return Instance of the following:
044         *      org.json.simple.JSONObject,
045         *      org.json.simple.JSONArray,
046         *      java.lang.String,
047         *      java.lang.Number,
048         *      java.lang.Boolean,
049         *      null
050         * 
051         * @deprecated this method may throw an {@code Error} instead of returning
052         * {@code null}; please use {@link JSONValue#parseWithException(Reader)}
053         * instead
054         */
055        public static Object parse(Reader in){
056                try{
057                        JSONParser parser=new JSONParser();
058                        return parser.parse(in);
059                }
060                catch(Exception e){
061                        return null;
062                }
063        }
064        
065        /**
066         * Parse JSON text into java object from the given string. 
067         * Please use parseWithException() if you don't want to ignore the exception.
068         * 
069         * @see org.json.simple.parser.JSONParser#parse(Reader)
070         * @see #parseWithException(Reader)
071         * 
072         * @param s description omitted.
073         * @return Instance of the following:
074         *      org.json.simple.JSONObject,
075         *      org.json.simple.JSONArray,
076         *      java.lang.String,
077         *      java.lang.Number,
078         *      java.lang.Boolean,
079         *      null
080         * 
081         * @deprecated this method may throw an {@code Error} instead of returning
082         * {@code null}; please use {@link JSONValue#parseWithException(String)}
083         * instead
084         */
085        public static Object parse(String s){
086                StringReader in=new StringReader(s);
087                return parse(in);
088        }
089        
090        /**
091         * Parse JSON text into java object from the input source.
092         * 
093         * @see org.json.simple.parser.JSONParser
094         * 
095         * @param in description omitted.
096         * @return Instance of the following:
097         *      org.json.simple.JSONObject,
098         *      org.json.simple.JSONArray,
099         *      java.lang.String,
100         *      java.lang.Number,
101         *      java.lang.Boolean,
102         *      null
103         * 
104         * @throws IOException description omitted.
105         * @throws ParseException description omitted.
106         */
107        public static Object parseWithException(Reader in) throws IOException, ParseException{
108                JSONParser parser=new JSONParser();
109                return parser.parse(in);
110        }
111        
112        /**
113         * description omitted.
114         *
115         * @param s description omitted.
116         * @return description omitted.
117         * @throws ParseException description omitted.
118         */
119        public static Object parseWithException(String s) throws ParseException{
120                JSONParser parser=new JSONParser();
121                return parser.parse(s);
122        }
123        
124    /**
125     * Encode an object into JSON text and write it to out.
126     * <p>
127     * 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.
128     * <p>
129     * DO NOT call this method from writeJSONString(Writer) of a class that implements both JSONStreamAware and (Map or List) with 
130     * "this" as the first parameter, use JSONObject.writeJSONString(Map, Writer) or JSONArray.writeJSONString(List, Writer) instead. 
131     * 
132     * @see org.json.simple.JSONObject#writeJSONString(Map, Writer)
133     * @see org.json.simple.JSONArray#writeJSONString(Collection, Writer)
134     * 
135     * @param value description omitted.
136     * @param out description omitted.
137     * @throws IOException description omitted.
138     */
139        public static void writeJSONString(Object value, Writer out) throws IOException {
140                if(value == null){
141                        out.write("null");
142                        return;
143                }
144                
145                if(value instanceof String){            
146            out.write('\"');
147                        out.write(escape((String)value));
148            out.write('\"');
149                        return;
150                }
151                
152                if(value instanceof Double){
153                        if(((Double)value).isInfinite() || ((Double)value).isNaN())
154                                out.write("null");
155                        else
156                                out.write(value.toString());
157                        return;
158                }
159                
160                if(value instanceof Float){
161                        if(((Float)value).isInfinite() || ((Float)value).isNaN())
162                                out.write("null");
163                        else
164                                out.write(value.toString());
165                        return;
166                }               
167                
168                if(value instanceof Number){
169                        out.write(value.toString());
170                        return;
171                }
172                
173                if(value instanceof Boolean){
174                        out.write(value.toString());
175                        return;
176                }
177                
178                if((value instanceof JSONStreamAware)){
179                        ((JSONStreamAware)value).writeJSONString(out);
180                        return;
181                }
182                
183                if((value instanceof JSONAware)){
184                        out.write(((JSONAware)value).toJSONString());
185                        return;
186                }
187                
188                if(value instanceof Map){
189                        JSONObject.writeJSONString((Map)value, out);
190                        return;
191                }
192                
193                if(value instanceof Collection){
194                        JSONArray.writeJSONString((Collection)value, out);
195            return;
196                }
197                
198                if(value instanceof byte[]){
199                        JSONArray.writeJSONString((byte[])value, out);
200                        return;
201                }
202                
203                if(value instanceof short[]){
204                        JSONArray.writeJSONString((short[])value, out);
205                        return;
206                }
207                
208                if(value instanceof int[]){
209                        JSONArray.writeJSONString((int[])value, out);
210                        return;
211                }
212                
213                if(value instanceof long[]){
214                        JSONArray.writeJSONString((long[])value, out);
215                        return;
216                }
217                
218                if(value instanceof float[]){
219                        JSONArray.writeJSONString((float[])value, out);
220                        return;
221                }
222                
223                if(value instanceof double[]){
224                        JSONArray.writeJSONString((double[])value, out);
225                        return;
226                }
227                
228                if(value instanceof boolean[]){
229                        JSONArray.writeJSONString((boolean[])value, out);
230                        return;
231                }
232                
233                if(value instanceof char[]){
234                        JSONArray.writeJSONString((char[])value, out);
235                        return;
236                }
237                
238                if(value instanceof Object[]){
239                        JSONArray.writeJSONString((Object[])value, out);
240                        return;
241                }
242                
243                out.write(value.toString());
244        }
245
246        /**
247         * Convert an object to JSON text.
248         * <p>
249         * If this object is a Map or a List, and it's also a JSONAware, JSONAware will be considered firstly.
250         * <p>
251         * DO NOT call this method from toJSONString() of a class that implements both JSONAware and Map or List with 
252         * "this" as the parameter, use JSONObject.toJSONString(Map) or JSONArray.toJSONString(List) instead. 
253         * 
254         * @see org.json.simple.JSONObject#toJSONString(Map)
255         * @see org.json.simple.JSONArray#toJSONString(Collection)
256         * 
257         * @param value description omitted.
258         * @return JSON text, or "null" if value is null or it's an NaN or an INF number.
259         */
260        public static String toJSONString(Object value){
261                final StringWriter writer = new StringWriter();
262                
263                try{
264                        writeJSONString(value, writer);
265                        return writer.toString();
266                } catch(IOException e){
267                        // This should never happen for a StringWriter
268                        throw new RuntimeException(e);
269                }
270        }
271
272        /**
273         * Escape quotes, \, /, \r, \n, \b, \f, \t and other control characters (U+0000 through U+001F).
274         * @param s description omitted.
275         * @return description omitted.
276         */
277        public static String escape(String s){
278                if(s==null)
279                        return null;
280        StringBuffer sb = new StringBuffer();
281        escape(s, sb);
282        return sb.toString();
283    }
284
285    /**
286     * @param s - Must not be null.
287     * @param sb description omitted.
288     */
289    static void escape(String s, StringBuffer sb) {
290        final int len = s.length();
291                for(int i=0;i<len;i++){
292                        char ch=s.charAt(i);
293                        switch(ch){
294                        case '"':
295                                sb.append("\\\"");
296                                break;
297                        case '\\':
298                                sb.append("\\\\");
299                                break;
300                        case '\b':
301                                sb.append("\\b");
302                                break;
303                        case '\f':
304                                sb.append("\\f");
305                                break;
306                        case '\n':
307                                sb.append("\\n");
308                                break;
309                        case '\r':
310                                sb.append("\\r");
311                                break;
312                        case '\t':
313                                sb.append("\\t");
314                                break;
315                        case '/':
316                                sb.append("\\/");
317                                break;
318                        default:
319                //Reference: http://www.unicode.org/versions/Unicode5.1.0/
320                                if((ch>='\u0000' && ch<='\u001F') || (ch>='\u007F' && ch<='\u009F') || (ch>='\u2000' && ch<='\u20FF')){
321                                        String ss=Integer.toHexString(ch);
322                                        sb.append("\\u");
323                                        for(int k=0;k<4-ss.length();k++){
324                                                sb.append('0');
325                                        }
326                                        sb.append(ss.toUpperCase());
327                                }
328                                else{
329                                        sb.append(ch);
330                                }
331                        }
332                }//for
333        }
334
335}