001/* =========================================================== 002 * JFreeChart : a free chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C) Copyright 2000-present, by David Gilbert and Contributors. 006 * 007 * Project Info: http://www.jfree.org/jfreechart/index.html 008 * 009 * JSON.simple 010 * ----------- 011 * The code in this file originates from the JSON.simple project by 012 * FangYidong<fangyidong@yahoo.com.cn>: 013 * 014 * https://code.google.com/p/json-simple/ 015 * 016 * which is licensed under the Apache Software License version 2.0. 017 * 018 * It has been modified locally and repackaged under 019 * org.jfree.data.json.impl.* to avoid conflicts with any other version that 020 * may be present on the classpath. 021 * 022 */ 023 024package org.jfree.data.json.impl; 025 026import java.io.IOException; 027import java.io.Writer; 028import java.util.List; 029import java.util.Map; 030 031/** 032 * Utility methods for JSON values. 033 * <br><br> 034 * This class is for internal use by JFreeChart, it is not 035 * part of the supported API and you should not call it directly. If you need 036 * JSON support in your project you should include JSON.simple 037 * (https://code.google.com/p/json-simple/) or some other JSON library directly 038 * in your project. 039 */ 040public class JSONValue { 041 042// /** 043// * Parse JSON text into java object from the input source. 044// * Please use parseWithException() if you don't want to ignore the 045// * exception. 046// * 047// * @see com.orsoncharts.util.json.parser.JSONParser#parse(Reader) 048// * @see #parseWithException(Reader) 049// * 050// * @param in the input reader. 051// * @return Instance of the following: 052// * com.orsoncharts.util.json.JSONObject, 053// * com.orsoncharts.util.json.JSONArray, 054// * java.lang.String, 055// * java.lang.Number, 056// * java.lang.Boolean, 057// * null 058// */ 059// public static Object parse(Reader in){ 060// try { 061// JSONParser parser = new JSONParser(); 062// return parser.parse(in); 063// } 064// catch (Exception e) { 065// return null; 066// } 067// } 068// 069// /** 070// * Parses an object from a string. 071// * 072// * @param s the string. 073// * 074// * @return An object. 075// */ 076// public static Object parse(String s){ 077// StringReader in = new StringReader(s); 078// return parse(in); 079// } 080// 081// /** 082// * Parse JSON text into java object from the input source. 083// * 084// * @see com.orsoncharts.util.json.parser.JSONParser 085// * 086// * @param in the input reader ({@code null} not permitted). 087// * 088// * @return Instance of the following: 089// * com.orsoncharts.util.json.JSONObject, 090// * com.orsoncharts.util.json.JSONArray, 091// * java.lang.String, 092// * java.lang.Number, 093// * java.lang.Boolean, 094// * null 095// * 096// * @throws IOException if there is an I/O problem. 097// * @throws ParseException if there is a parsing problem. 098// */ 099// public static Object parseWithException(Reader in) throws IOException, 100// ParseException{ 101// JSONParser parser = new JSONParser(); 102// return parser.parse(in); 103// } 104// 105// /** 106// * Parses an object from a JSON string. 107// * 108// * @param s the string. 109// * 110// * @return An object. 111// * 112// * @throws ParseException if there is a parsing problem. 113// */ 114// public static Object parseWithException(String s) throws ParseException{ 115// JSONParser parser = new JSONParser(); 116// return parser.parse(s); 117// } 118 119 /** 120 * Encode an object into JSON text and write it to out. 121 * <p> 122 * If this object is a {@code Map} or a {@code List}, and it's 123 * also a {@link JSONStreamAware} or a {@link JSONAware}, 124 * {@code JSONStreamAware} or {@code JSONAware} will be 125 * considered firstly. 126 * <p> 127 * DO NOT call this method from writeJSONString(Writer) of a class that 128 * implements both JSONStreamAware and (Map or List) with 129 * "this" as the first parameter, use JSONObject.writeJSONString(Map, 130 * Writer) or JSONArray.writeJSONString(List, Writer) instead. 131 * 132 * @see org.jfree.data.json.impl.JSONObject#writeJSONString(Map, Writer) 133 * @see org.jfree.data.json.impl.JSONArray#writeJSONString(List, Writer) 134 * 135 * @param value the value. 136 * @param out the output writer. 137 * @throws IOException if there is an I/O problem. 138 */ 139 public static void writeJSONString(Object value, Writer out) 140 throws IOException { 141 if (value == null) { 142 out.write("null"); 143 return; 144 } 145 146 if (value instanceof String) { 147 out.write('\"'); 148 out.write(escape((String) value)); 149 out.write('\"'); 150 return; 151 } 152 153 if (value instanceof Double) { 154 if(((Double) value).isInfinite() || ((Double) value).isNaN()) { 155 out.write("null"); 156 } 157 else { 158 out.write(value.toString()); 159 } 160 return; 161 } 162 163 if (value instanceof Float) { 164 if (((Float) value).isInfinite() || ((Float) value).isNaN()) { 165 out.write("null"); 166 } 167 else { 168 out.write(value.toString()); 169 } 170 return; 171 } 172 173 if (value instanceof Number) { 174 out.write(value.toString()); 175 return; 176 } 177 178 if (value instanceof Boolean) { 179 out.write(value.toString()); 180 return; 181 } 182 183 if ((value instanceof JSONStreamAware)) { 184 ((JSONStreamAware) value).writeJSONString(out); 185 return; 186 } 187 188 if ((value instanceof JSONAware)) { 189 out.write(((JSONAware) value).toJSONString()); 190 return; 191 } 192 193 if (value instanceof Map) { 194 JSONObject.writeJSONString((Map) value, out); 195 return; 196 } 197 198 if (value instanceof List) { 199 JSONArray.writeJSONString((List) value, out); 200 return; 201 } 202 203 out.write(value.toString()); 204 } 205 206 /** 207 * Convert an object to JSON text. 208 * <p> 209 * If this object is a Map or a List, and it's also a JSONAware, JSONAware 210 * will be considered firstly. 211 * <p> 212 * DO NOT call this method from toJSONString() of a class that implements 213 * both JSONAware and Map or List with 214 * "this" as the parameter, use JSONObject.toJSONString(Map) or 215 * JSONArray.toJSONString(List) instead. 216 * 217 * @see org.jfree.data.json.impl.JSONObject#toJSONString(Map) 218 * @see org.jfree.data.json.impl.JSONArray#toJSONString(List) 219 * 220 * @param value the value. 221 * @return JSON text, or "null" if value is null or it's an NaN or an INF 222 * number. 223 */ 224 public static String toJSONString(Object value){ 225 if (value == null) { 226 return "null"; 227 } 228 229 if (value instanceof String) { 230 return "\"" + escape((String) value) + "\""; 231 } 232 233 if (value instanceof Double){ 234 if(((Double) value).isInfinite() || ((Double) value).isNaN()) { 235 return "null"; 236 } 237 else { 238 return value.toString(); 239 } 240 } 241 242 if (value instanceof Float) { 243 if (((Float) value).isInfinite() || ((Float) value).isNaN()) { 244 return "null"; 245 } 246 else { 247 return value.toString(); 248 } 249 } 250 251 if (value instanceof Number) { 252 return value.toString(); 253 } 254 255 if (value instanceof Boolean) { 256 return value.toString(); 257 } 258 259 if ((value instanceof JSONAware)) { 260 return ((JSONAware) value).toJSONString(); 261 } 262 263 if (value instanceof Map) { 264 return JSONObject.toJSONString((Map) value); 265 } 266 267 if (value instanceof List) { 268 return JSONArray.toJSONString((List) value); 269 } 270 271 return value.toString(); 272 } 273 274 /** 275 * Escape quotes, \, /, \r, \n, \b, \f, \t and other control characters 276 * (U+0000 through U+001F). 277 * 278 * @param s the string to be escaped ({@code null} permitted). 279 * 280 * @return A string. 281 */ 282 public static String escape(String s) { 283 if (s == null) { 284 return null; 285 } 286 StringBuffer sb = new StringBuffer(); 287 escape(s, sb); 288 return sb.toString(); 289 } 290 291 /** 292 * @param s - Must not be null. 293 * @param sb 294 */ 295 static void escape(String s, StringBuffer sb) { 296 for(int i = 0; i < s.length(); i++) { 297 char ch = s.charAt(i); 298 switch(ch){ 299 case '"': 300 sb.append("\\\""); 301 break; 302 case '\\': 303 sb.append("\\\\"); 304 break; 305 case '\b': 306 sb.append("\\b"); 307 break; 308 case '\f': 309 sb.append("\\f"); 310 break; 311 case '\n': 312 sb.append("\\n"); 313 break; 314 case '\r': 315 sb.append("\\r"); 316 break; 317 case '\t': 318 sb.append("\\t"); 319 break; 320 case '/': 321 sb.append("\\/"); 322 break; 323 default: 324 //Reference: http://www.unicode.org/versions/Unicode5.1.0/ 325 if ((ch >= '\u0000' && ch <= '\u001F') 326 || (ch >= '\u007F' && ch <= '\u009F') 327 || (ch >= '\u2000' && ch <= '\u20FF')) { 328 String ss = Integer.toHexString(ch); 329 sb.append("\\u"); 330 for (int k = 0; k < 4 - ss.length(); k++) { 331 sb.append('0'); 332 } 333 sb.append(ss.toUpperCase()); 334 } 335 else { 336 sb.append(ch); 337 } 338 } 339 }//for 340 } 341 342}