| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -79,17 +79,6 @@ public class JSONObject { | |||
| 79 | 79 | */ | |
| 80 | 80 | private static final class Null { | |
| 81 | 81 | ||
| 82 | - /** | ||
| 83 | - * There is only intended to be a single instance of the NULL object, | ||
| 84 | - * so the clone method returns itself. | ||
| 85 | - * | ||
| 86 | - * @return NULL. | ||
| 87 | - */ | ||
| 88 | - @Override | ||
| 89 | - protected final Object clone() { | ||
| 90 | - return this; | ||
| 91 | - } | ||
| 92 | - | ||
| 93 | 82 | /** | |
| 94 | 83 | * A Null object is equal to the null value and to itself. | |
| 95 | 84 | * | |
@@ -180,7 +169,7 @@ public JSONObject(JSONObject jo, String ... names) { | |||
| 180 | 169 | for (int i = 0; i < names.length; i += 1) { | |
| 181 | 170 | try { | |
| 182 | 171 | this.putOnce(names[i], jo.opt(names[i])); | |
| 183 | - } catch (Exception ignore) { | ||
| 172 | + } catch (Exception ignore) { // exception thrown for missing key | ||
| 184 | 173 | } | |
| 185 | 174 | } | |
| 186 | 175 | } | |
@@ -221,83 +210,128 @@ public JSONObject(JSONTokener x, JSONParserConfiguration jsonParserConfiguration | |||
| 221 | 210 | throw x.syntaxError("A JSONObject text must begin with '{'"); | |
| 222 | 211 | } | |
| 223 | 212 | for (;;) { | |
| 224 | - c = x.nextClean(); | ||
| 225 | - switch (c) { | ||
| 213 | + if (parseJSONObject(x, jsonParserConfiguration, isInitial)) { | ||
| 214 | + return; | ||
| 215 | + } | ||
| 216 | + } | ||
| 217 | + } | ||
| 218 | + | ||
| 219 | + /** | ||
| 220 | + * Parses entirety of JSON object | ||
| 221 | + * | ||
| 222 | + * @param jsonTokener Parses text as tokens | ||
| 223 | + * @param jsonParserConfiguration Variable to pass parser custom configuration for json parsing. | ||
| 224 | + * @param isInitial True if start of document, else false | ||
| 225 | + * @return True if done building object, else false | ||
| 226 | + */ | ||
| 227 | + private boolean parseJSONObject(JSONTokener jsonTokener, JSONParserConfiguration jsonParserConfiguration, boolean isInitial) { | ||
| 228 | + Object obj; | ||
| 229 | + String key; | ||
| 230 | + char c; | ||
| 231 | + c = jsonTokener.nextClean(); | ||
| 232 | + | ||
| 233 | + switch (c) { | ||
| 226 | 234 | case 0: | |
| 227 | - throw x.syntaxError("A JSONObject text must end with '}'"); | ||
| 235 | + throw jsonTokener.syntaxError("A JSONObject text must end with '}'"); | ||
| 228 | 236 | case '}': | |
| 229 | - if (isInitial && jsonParserConfiguration.isStrictMode() && x.nextClean() != 0) { | ||
| 230 | - throw x.syntaxError("Strict mode error: Unparsed characters found at end of input text"); | ||
| 237 | + if (isInitial && jsonParserConfiguration.isStrictMode() && jsonTokener.nextClean() != 0) { | ||
| 238 | + throw jsonTokener.syntaxError("Strict mode error: Unparsed characters found at end of input text"); | ||
| 231 | 239 | } | |
| 232 | - return; | ||
| 240 | + return true; | ||
| 233 | 241 | default: | |
| 234 | - obj = x.nextSimpleValue(c); | ||
| 242 | + obj = jsonTokener.nextSimpleValue(c); | ||
| 235 | 243 | key = obj.toString(); | |
| 236 | - } | ||
| 244 | + } | ||
| 237 | 245 | ||
| 238 | - if (jsonParserConfiguration != null && jsonParserConfiguration.isStrictMode()) { | ||
| 239 | - if(obj instanceof Boolean) { | ||
| 240 | - throw x.syntaxError(String.format("Strict mode error: key '%s' cannot be boolean", key)); | ||
| 241 | - } | ||
| 242 | - if(obj == JSONObject.NULL) { | ||
| 243 | - throw x.syntaxError(String.format("Strict mode error: key '%s' cannot be null", key)); | ||
| 244 | - } | ||
| 245 | - if(obj instanceof Number) { | ||
| 246 | - throw x.syntaxError(String.format("Strict mode error: key '%s' cannot be number", key)); | ||
| 247 | - } | ||
| 248 | - } | ||
| 246 | + checkKeyForStrictMode(jsonTokener, jsonParserConfiguration, obj); | ||
| 249 | 247 | ||
| 250 | - // The key is followed by ':'. | ||
| 248 | + // The key is followed by ':'. | ||
| 249 | + c = jsonTokener.nextClean(); | ||
| 250 | + if (c != ':') { | ||
| 251 | + throw jsonTokener.syntaxError("Expected a ':' after a key"); | ||
| 252 | + } | ||
| 251 | 253 | ||
| 252 | - c = x.nextClean(); | ||
| 253 | - if (c != ':') { | ||
| 254 | - throw x.syntaxError("Expected a ':' after a key"); | ||
| 254 | + // Use syntaxError(..) to include error location | ||
| 255 | + if (key != null) { | ||
| 256 | + // Check if key exists | ||
| 257 | + boolean keyExists = this.opt(key) != null; | ||
| 258 | + if (keyExists && !jsonParserConfiguration.isOverwriteDuplicateKey()) { | ||
| 259 | + throw jsonTokener.syntaxError("Duplicate key \"" + key + "\""); | ||
| 255 | 260 | } | |
| 256 | 261 | ||
| 257 | - // Use syntaxError(..) to include error location | ||
| 258 | - | ||
| 259 | - if (key != null) { | ||
| 260 | - // Check if key exists | ||
| 261 | - boolean keyExists = this.opt(key) != null; | ||
| 262 | - if (keyExists && !jsonParserConfiguration.isOverwriteDuplicateKey()) { | ||
| 263 | - throw x.syntaxError("Duplicate key \"" + key + "\""); | ||
| 264 | - } | ||
| 265 | - | ||
| 266 | - Object value = x.nextValue(); | ||
| 267 | - // Only add value if non-null | ||
| 268 | - if (value != null) { | ||
| 269 | - this.put(key, value); | ||
| 270 | - } | ||
| 262 | + Object value = jsonTokener.nextValue(); | ||
| 263 | + // Only add value if non-null | ||
| 264 | + if (value != null) { | ||
| 265 | + this.put(key, value); | ||
| 271 | 266 | } | |
| 267 | + } | ||
| 272 | 268 | ||
| 273 | - // Pairs are separated by ','. | ||
| 269 | + // Pairs are separated by ','. | ||
| 270 | + if (parseEndOfKeyValuePair(jsonTokener, jsonParserConfiguration, isInitial)) { | ||
| 271 | + return true; | ||
| 272 | + } | ||
| 273 | + // Not finished parsing | ||
| 274 | + return false; | ||
| 275 | + } | ||
| 274 | 276 | ||
| 275 | - switch (x.nextClean()) { | ||
| 277 | + /** | ||
| 278 | + * Checks for valid end of key:value pair | ||
| 279 | + * @param jsonTokener Parses text as tokens | ||
| 280 | + * @param jsonParserConfiguration Variable to pass parser custom configuration for json parsing. | ||
| 281 | + * @param isInitial True if end of JSON object, else false | ||
| 282 | + * @return | ||
| 283 | + */ | ||
| 284 | + private static boolean parseEndOfKeyValuePair(JSONTokener jsonTokener, JSONParserConfiguration jsonParserConfiguration, boolean isInitial) { | ||
| 285 | + switch (jsonTokener.nextClean()) { | ||
| 276 | 286 | case ';': | |
| 277 | 287 | // In strict mode semicolon is not a valid separator | |
| 278 | 288 | if (jsonParserConfiguration.isStrictMode()) { | |
| 279 | - throw x.syntaxError("Strict mode error: Invalid character ';' found"); | ||
| 289 | + throw jsonTokener.syntaxError("Strict mode error: Invalid character ';' found"); | ||
| 280 | 290 | } | |
| 291 | + break; | ||
| 281 | 292 | case ',': | |
| 282 | - if (x.nextClean() == '}') { | ||
| 293 | + if (jsonTokener.nextClean() == '}') { | ||
| 283 | 294 | // trailing commas are not allowed in strict mode | |
| 284 | 295 | if (jsonParserConfiguration.isStrictMode()) { | |
| 285 | - throw x.syntaxError("Strict mode error: Expected another object element"); | ||
| 296 | + throw jsonTokener.syntaxError("Strict mode error: Expected another object element"); | ||
| 286 | 297 | } | |
| 287 | - return; | ||
| 298 | + // End of JSON object | ||
| 299 | + return true; | ||
| 288 | 300 | } | |
| 289 | - if (x.end()) { | ||
| 290 | - throw x.syntaxError("A JSONObject text must end with '}'"); | ||
| 301 | + if (jsonTokener.end()) { | ||
| 302 | + throw jsonTokener.syntaxError("A JSONObject text must end with '}'"); | ||
| 291 | 303 | } | |
| 292 | - x.back(); | ||
| 304 | + jsonTokener.back(); | ||
| 293 | 305 | break; | |
| 294 | 306 | case '}': | |
| 295 | - if (isInitial && jsonParserConfiguration.isStrictMode() && x.nextClean() != 0) { | ||
| 296 | - throw x.syntaxError("Strict mode error: Unparsed characters found at end of input text"); | ||
| 307 | + if (isInitial && jsonParserConfiguration.isStrictMode() && jsonTokener.nextClean() != 0) { | ||
| 308 | + throw jsonTokener.syntaxError("Strict mode error: Unparsed characters found at end of input text"); | ||
| 297 | 309 | } | |
| 298 | - return; | ||
| 310 | + // End of JSON object | ||
| 311 | + return true; | ||
| 299 | 312 | default: | |
| 300 | - throw x.syntaxError("Expected a ',' or '}'"); | ||
| 313 | + throw jsonTokener.syntaxError("Expected a ',' or '}'"); | ||
| 314 | + } | ||
| 315 | + // Not at end of JSON object | ||
| 316 | + return false; | ||
| 317 | + } | ||
| 318 | + | ||
| 319 | + /** | ||
| 320 | + * Throws error if key violates strictMode | ||
| 321 | + * @param jsonTokener Parses text as tokens | ||
| 322 | + * @param jsonParserConfiguration Variable to pass parser custom configuration for json parsing. | ||
| 323 | + * @param obj Value to be checked | ||
| 324 | + */ | ||
| 325 | + private static void checkKeyForStrictMode(JSONTokener jsonTokener, JSONParserConfiguration jsonParserConfiguration, Object obj) { | ||
| 326 | + if (jsonParserConfiguration != null && jsonParserConfiguration.isStrictMode()) { | ||
| 327 | + if(obj instanceof Boolean) { | ||
| 328 | + throw jsonTokener.syntaxError(String.format("Strict mode error: key '%s' cannot be boolean", obj.toString())); | ||
| 329 | + } | ||
| 330 | + if(obj == JSONObject.NULL) { | ||
| 331 | + throw jsonTokener.syntaxError(String.format("Strict mode error: key '%s' cannot be null", obj.toString())); | ||
| 332 | + } | ||
| 333 | + if(obj instanceof Number) { | ||
| 334 | + throw jsonTokener.syntaxError(String.format("Strict mode error: key '%s' cannot be number", obj.toString())); | ||
| 301 | 335 | } | |
| 302 | 336 | } | |
| 303 | 337 | } | |
| Back | FazBrowse Home | New Git URL |
0 commit comments