aboutsummaryrefslogtreecommitdiff
path: root/src/org/json/simple/JSONValue.java
blob: 3d423153af2658b477f3e2c0960ac39b5273c188 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
/*
 * $Id: JSONValue.java,v 1.1 2006/04/15 14:37:04 platform Exp $
 * Created on 2006-4-15
 */
package org.json.simple;

import java.io.IOException;
import java.util.Collection;
// import java.util.List;
import java.util.Map;

import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;

import rejava.io.Reader;
import rejava.io.StringReader;
import rejava.io.StringWriter;
import rejava.io.Writer;

/**
 * @author FangYidong<fangyidong@yahoo.com.cn>
 */
public class JSONValue {
	/**
	 * Parse JSON text into java object from the input source. Please use
	 * parseWithException() if you don't want to ignore the exception.
	 * 
	 * @see org.json.simple.parser.JSONParser#parse(Reader)
	 * @see #parseWithException(Reader)
	 * 
	 * @param in
	 * @return Instance of the following: org.json.simple.JSONObject,
	 *         org.json.simple.JSONArray, java.lang.String, java.lang.Number,
	 *         java.lang.Boolean, null
	 * 
	 * @deprecated this method may throw an {@code Error} instead of returning
	 *             {@code null}; please use
	 *             {@link JSONValue#parseWithException(Reader)} instead
	 */
	@Deprecated
	public static Object parse(final Reader in) {
		try {
			final JSONParser parser = new JSONParser();
			return parser.parse(in);
		} catch (final Exception e) {
			return null;
		}
	}

	/**
	 * Parse JSON text into java object from the given string. Please use
	 * parseWithException() if you don't want to ignore the exception.
	 * 
	 * @see org.json.simple.parser.JSONParser#parse(Reader)
	 * @see #parseWithException(Reader)
	 * 
	 * @param s
	 * @return Instance of the following: org.json.simple.JSONObject,
	 *         org.json.simple.JSONArray, java.lang.String, java.lang.Number,
	 *         java.lang.Boolean, null
	 * 
	 * @deprecated this method may throw an {@code Error} instead of returning
	 *             {@code null}; please use
	 *             {@link JSONValue#parseWithException(String)} instead
	 */
	@Deprecated
	public static Object parse(final String s) {
		final StringReader in = new StringReader(s);
		return JSONValue.parse(in);
	}

	/**
	 * Parse JSON text into java object from the input source.
	 * 
	 * @see org.json.simple.parser.JSONParser
	 * 
	 * @param in
	 * @return Instance of the following: org.json.simple.JSONObject,
	 *         org.json.simple.JSONArray, java.lang.String, java.lang.Number,
	 *         java.lang.Boolean, null
	 * 
	 * @throws IOException
	 * @throws ParseException
	 */
	public static Object parseWithException(final Reader in) throws IOException, ParseException {
		final JSONParser parser = new JSONParser();
		return parser.parse(in);
	}

	public static Object parseWithException(final String s) throws ParseException {
		final JSONParser parser = new JSONParser();
		return parser.parse(s);
	}

	/**
	 * Encode an object into JSON text and write it to out.
	 * <p>
	 * 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.
	 * <p>
	 * DO NOT call this method from writeJSONString(Writer) of a class that
	 * implements both JSONStreamAware and (Map or List) with "this" as the
	 * first parameter, use JSONObject.writeJSONString(Map, Writer) or
	 * JSONArray.writeJSONString(List, Writer) instead.
	 * 
	 * @see org.json.simple.JSONObject#writeJSONString(Map, Writer)
	 * @see org.json.simple.JSONArray#writeJSONString(List, Writer)
	 * 
	 * @param value
	 * @param writer
	 */
	@SuppressWarnings("rawtypes")
	public static void writeJSONString(final Object value, final Writer out) throws IOException {
		if (value == null) {
			out.write("null");
			return;
		}

		if (value instanceof String) {
			out.write('\"');
			out.write(JSONValue.escape((String) value));
			out.write('\"');
			return;
		}

		if (value instanceof Double) {
			if (((Double) value).isInfinite() || ((Double) value).isNaN()) {
				out.write("null");
			} else {
				out.write(value.toString());
			}
			return;
		}

		if (value instanceof Float) {
			if (((Float) value).isInfinite() || ((Float) value).isNaN()) {
				out.write("null");
			} else {
				out.write(value.toString());
			}
			return;
		}

		if (value instanceof Number) {
			out.write(value.toString());
			return;
		}

		if (value instanceof Boolean) {
			out.write(value.toString());
			return;
		}

		if ((value instanceof JSONStreamAware)) {
			((JSONStreamAware) value).writeJSONString(out);
			return;
		}

		if ((value instanceof JSONAware)) {
			out.write(((JSONAware) value).toJSONString());
			return;
		}

		if (value instanceof Map) {
			JSONObject.writeJSONString((Map) value, out);
			return;
		}

		if (value instanceof Collection) {
			JSONArray.writeJSONString((Collection) value, out);
			return;
		}

		if (value instanceof byte[]) {
			JSONArray.writeJSONString((byte[]) value, out);
			return;
		}

		if (value instanceof short[]) {
			JSONArray.writeJSONString((short[]) value, out);
			return;
		}

		if (value instanceof int[]) {
			JSONArray.writeJSONString((int[]) value, out);
			return;
		}

		if (value instanceof long[]) {
			JSONArray.writeJSONString((long[]) value, out);
			return;
		}

		if (value instanceof float[]) {
			JSONArray.writeJSONString((float[]) value, out);
			return;
		}

		if (value instanceof double[]) {
			JSONArray.writeJSONString((double[]) value, out);
			return;
		}

		if (value instanceof boolean[]) {
			JSONArray.writeJSONString((boolean[]) value, out);
			return;
		}

		if (value instanceof char[]) {
			JSONArray.writeJSONString((char[]) value, out);
			return;
		}

		if (value instanceof Object[]) {
			JSONArray.writeJSONString((Object[]) value, out);
			return;
		}

		out.write(value.toString());
	}

	/**
	 * Convert an object to JSON text.
	 * <p>
	 * If this object is a Map or a List, and it's also a JSONAware, JSONAware
	 * will be considered firstly.
	 * <p>
	 * DO NOT call this method from toJSONString() of a class that implements
	 * both JSONAware and Map or List with "this" as the parameter, use
	 * JSONObject.toJSONString(Map) or JSONArray.toJSONString(List) instead.
	 * 
	 * @see org.json.simple.JSONObject#toJSONString(Map)
	 * @see org.json.simple.JSONArray#toJSONString(List)
	 * 
	 * @param value
	 * @return JSON text, or "null" if value is null or it's an NaN or an INF
	 *         number.
	 */
	public static String toJSONString(final Object value) {
		final StringWriter writer = new StringWriter();

		try {
			JSONValue.writeJSONString(value, writer);
			return writer.toString();
		} catch (final IOException e) {
			// This should never happen for a StringWriter
			throw new RuntimeException(e);
		}
	}

	/**
	 * Escape quotes, \, /, \r, \n, \b, \f, \t and other control characters
	 * (U+0000 through U+001F).
	 * 
	 * @param s
	 * @return
	 */
	public static String escape(final String s) {
		if (s == null) {
			return null;
		}
		final StringBuffer sb = new StringBuffer();
		JSONValue.escape(s, sb);
		return sb.toString();
	}

	/**
	 * @param s
	 *            - Must not be null.
	 * @param sb
	 */
	static void escape(final String s, final StringBuffer sb) {
		final int len = s.length();
		for (int i = 0; i < len; i++) {
			final char ch = s.charAt(i);
			switch (ch) {
			case '"':
				sb.append("\\\"");
				break;
			case '\\':
				sb.append("\\\\");
				break;
			case '\b':
				sb.append("\\b");
				break;
			case '\f':
				sb.append("\\f");
				break;
			case '\n':
				sb.append("\\n");
				break;
			case '\r':
				sb.append("\\r");
				break;
			case '\t':
				sb.append("\\t");
				break;
			case '/':
				sb.append("\\/");
				break;
			default:
				// Reference: http://www.unicode.org/versions/Unicode5.1.0/
				if (((ch >= '\u0000') && (ch <= '\u001F')) || ((ch >= '\u007F') && (ch <= '\u009F')) || ((ch >= '\u2000') && (ch <= '\u20FF'))) {
					final String ss = Integer.toHexString(ch);
					sb.append("\\u");
					for (int k = 0; k < (4 - ss.length()); k++) {
						sb.append('0');
					}
					sb.append(ss.toUpperCase());
				} else {
					sb.append(ch);
				}
			}
		}// for
	}

}