From 2a39f471970fda0e806e2d678e00ede53de500f3 Mon Sep 17 00:00:00 2001 From: Douglas Crockford Date: Thu, 24 Nov 2011 07:40:50 -0800 Subject: [PATCH] ?: --- JSONML.java | 505 ++++++++++++++++++++++++----------------------- JSONTokener.java | 91 ++++----- JSONWriter.java | 14 +- 3 files changed, 308 insertions(+), 302 deletions(-) diff --git a/JSONML.java b/JSONML.java index 936d16e..c329179 100755 --- a/JSONML.java +++ b/JSONML.java @@ -32,7 +32,7 @@ import java.util.Iterator; * JSONObject, and to covert a JSONArray or JSONObject into an XML text using * the JsonML transform. * @author JSON.org - * @version 2011-10-05 + * @version 2011-11-24 */ public class JSONML { @@ -48,16 +48,16 @@ public class JSONML { private static Object parse( XMLTokener x, boolean arrayForm, - JSONArray ja + JSONArray ja ) throws JSONException { String attribute; char c; - String closeTag = null; + String closeTag = null; int i; JSONArray newja = null; JSONObject newjo = null; Object token; - String tagName = null; + String tagName = null; // Test for and skip past these forms: // @@ -69,165 +69,166 @@ public class JSONML { if (!x.more()) { throw x.syntaxError("Bad XML"); } - token = x.nextContent(); - if (token == XML.LT) { - token = x.nextToken(); - if (token instanceof Character) { - if (token == XML.SLASH) { + token = x.nextContent(); + if (token == XML.LT) { + token = x.nextToken(); + if (token instanceof Character) { + if (token == XML.SLASH) { // Close tag "); - } - x.back(); - } else if (c == '[') { - token = x.nextToken(); - if (token.equals("CDATA") && x.next() == '[') { - if (ja != null) { - ja.put(x.nextCDATA()); - } - } else { - throw x.syntaxError("Expected 'CDATA['"); - } - } else { - i = 1; - do { - token = x.nextMeta(); - if (token == null) { - throw x.syntaxError("Missing '>' after ' 0); - } - } else if (token == XML.QUEST) { + c = x.next(); + if (c == '-') { + if (x.next() == '-') { + x.skipPast("-->"); + } + x.back(); + } else if (c == '[') { + token = x.nextToken(); + if (token.equals("CDATA") && x.next() == '[') { + if (ja != null) { + ja.put(x.nextCDATA()); + } + } else { + throw x.syntaxError("Expected 'CDATA['"); + } + } else { + i = 1; + do { + token = x.nextMeta(); + if (token == null) { + throw x.syntaxError("Missing '>' after ' 0); + } + } else if (token == XML.QUEST) { // "); - } else { - throw x.syntaxError("Misshaped tag"); - } + x.skipPast("?>"); + } else { + throw x.syntaxError("Misshaped tag"); + } // Open tag < - } else { - if (!(token instanceof String)) { - throw x.syntaxError("Bad tagName '" + token + "'."); - } - tagName = (String)token; - newja = new JSONArray(); - newjo = new JSONObject(); - if (arrayForm) { - newja.put(tagName); - if (ja != null) { - ja.put(newja); - } - } else { - newjo.put("tagName", tagName); - if (ja != null) { - ja.put(newjo); - } - } - token = null; - for (;;) { - if (token == null) { - token = x.nextToken(); - } - if (token == null) { - throw x.syntaxError("Misshaped tag"); - } - if (!(token instanceof String)) { - break; - } + } else { + if (!(token instanceof String)) { + throw x.syntaxError("Bad tagName '" + token + "'."); + } + tagName = (String)token; + newja = new JSONArray(); + newjo = new JSONObject(); + if (arrayForm) { + newja.put(tagName); + if (ja != null) { + ja.put(newja); + } + } else { + newjo.put("tagName", tagName); + if (ja != null) { + ja.put(newjo); + } + } + token = null; + for (;;) { + if (token == null) { + token = x.nextToken(); + } + if (token == null) { + throw x.syntaxError("Misshaped tag"); + } + if (!(token instanceof String)) { + break; + } // attribute = value - attribute = (String)token; - if (!arrayForm && (attribute == "tagName" || attribute == "childNode")) { + attribute = (String)token; + if (!arrayForm && (attribute == "tagName" || attribute == "childNode")) { throw x.syntaxError("Reserved attribute."); - } - token = x.nextToken(); - if (token == XML.EQ) { - token = x.nextToken(); - if (!(token instanceof String)) { - throw x.syntaxError("Missing value"); - } - newjo.accumulate(attribute, XML.stringToValue((String)token)); - token = null; - } else { - newjo.accumulate(attribute, ""); - } - } + } + token = x.nextToken(); + if (token == XML.EQ) { + token = x.nextToken(); + if (!(token instanceof String)) { + throw x.syntaxError("Missing value"); + } + newjo.accumulate(attribute, XML.stringToValue((String)token)); + token = null; + } else { + newjo.accumulate(attribute, ""); + } + } if (arrayForm && newjo.length() > 0) { - newja.put(newjo); + newja.put(newjo); } // Empty tag <.../> - if (token == XML.SLASH) { - if (x.nextToken() != XML.GT) { - throw x.syntaxError("Misshaped tag"); - } - if (ja == null) { - if (arrayForm) { - return newja; - } else { - return newjo; - } - } + if (token == XML.SLASH) { + if (x.nextToken() != XML.GT) { + throw x.syntaxError("Misshaped tag"); + } + if (ja == null) { + if (arrayForm) { + return newja; + } else { + return newjo; + } + } // Content, between <...> and - } else { - if (token != XML.GT) { - throw x.syntaxError("Misshaped tag"); - } - closeTag = (String)parse(x, arrayForm, newja); - if (closeTag != null) { - if (!closeTag.equals(tagName)) { - throw x.syntaxError("Mismatched '" + tagName + - "' and '" + closeTag + "'"); - } - tagName = null; - if (!arrayForm && newja.length() > 0) { - newjo.put("childNodes", newja); - } - if (ja == null) { - if (arrayForm) { - return newja; - } else { - return newjo; - } - } - } - } - } - } else { - if (ja != null) { - ja.put(token instanceof String ? - XML.stringToValue((String)token) : token); - } - } + } else { + if (token != XML.GT) { + throw x.syntaxError("Misshaped tag"); + } + closeTag = (String)parse(x, arrayForm, newja); + if (closeTag != null) { + if (!closeTag.equals(tagName)) { + throw x.syntaxError("Mismatched '" + tagName + + "' and '" + closeTag + "'"); + } + tagName = null; + if (!arrayForm && newja.length() > 0) { + newjo.put("childNodes", newja); + } + if (ja == null) { + if (arrayForm) { + return newja; + } else { + return newjo; + } + } + } + } + } + } else { + if (ja != null) { + ja.put(token instanceof String + ? XML.stringToValue((String)token) + : token); + } + } } } @@ -245,7 +246,7 @@ public class JSONML { * @throws JSONException */ public static JSONArray toJSONArray(String string) throws JSONException { - return toJSONArray(new XMLTokener(string)); + return toJSONArray(new XMLTokener(string)); } @@ -262,7 +263,7 @@ public class JSONML { * @throws JSONException */ public static JSONArray toJSONArray(XMLTokener x) throws JSONException { - return (JSONArray)parse(x, true, null); + return (JSONArray)parse(x, true, null); } @@ -280,7 +281,7 @@ public class JSONML { * @throws JSONException */ public static JSONObject toJSONObject(XMLTokener x) throws JSONException { - return (JSONObject)parse(x, false, null); + return (JSONObject)parse(x, false, null); } @@ -298,7 +299,7 @@ public class JSONML { * @throws JSONException */ public static JSONObject toJSONObject(String string) throws JSONException { - return toJSONObject(new XMLTokener(string)); + return toJSONObject(new XMLTokener(string)); } @@ -309,75 +310,75 @@ public class JSONML { * @throws JSONException */ public static String toString(JSONArray ja) throws JSONException { - int i; - JSONObject jo; - String key; - Iterator keys; - int length; - Object object; - StringBuffer sb = new StringBuffer(); - String tagName; - String value; + int i; + JSONObject jo; + String key; + Iterator keys; + int length; + Object object; + StringBuffer sb = new StringBuffer(); + String tagName; + String value; // Emit = length) { - sb.append('/'); - sb.append('>'); - } else { - sb.append('>'); - do { - object = ja.get(i); - i += 1; - if (object != null) { - if (object instanceof String) { - sb.append(XML.escape(object.toString())); - } else if (object instanceof JSONObject) { - sb.append(toString((JSONObject)object)); - } else if (object instanceof JSONArray) { - sb.append(toString((JSONArray)object)); - } - } - } while (i < length); - sb.append('<'); - sb.append('/'); - sb.append(tagName); - sb.append('>'); - } + length = ja.length(); + if (i >= length) { + sb.append('/'); + sb.append('>'); + } else { + sb.append('>'); + do { + object = ja.get(i); + i += 1; + if (object != null) { + if (object instanceof String) { + sb.append(XML.escape(object.toString())); + } else if (object instanceof JSONObject) { + sb.append(toString((JSONObject)object)); + } else if (object instanceof JSONArray) { + sb.append(toString((JSONArray)object)); + } + } + } while (i < length); + sb.append('<'); + sb.append('/'); + sb.append(tagName); + sb.append('>'); + } return sb.toString(); } @@ -390,27 +391,27 @@ public class JSONML { * @return An XML string. * @throws JSONException */ - public static String toString(JSONObject jo) throws JSONException { - StringBuffer sb = new StringBuffer(); - int i; - JSONArray ja; - String key; - Iterator keys; - int length; - Object object; - String tagName; - String value; + public static String toString(JSONObject jo) throws JSONException { + StringBuffer sb = new StringBuffer(); + int i; + JSONArray ja; + String key; + Iterator keys; + int length; + Object object; + String tagName; + String value; //Emit '); - } else { - sb.append('>'); - length = ja.length(); - for (i = 0; i < length; i += 1) { - object = ja.get(i); - if (object != null) { - if (object instanceof String) { - sb.append(XML.escape(object.toString())); + ja = jo.optJSONArray("childNodes"); + if (ja == null) { + sb.append('/'); + sb.append('>'); + } else { + sb.append('>'); + length = ja.length(); + for (i = 0; i < length; i += 1) { + object = ja.get(i); + if (object != null) { + if (object instanceof String) { + sb.append(XML.escape(object.toString())); } else if (object instanceof JSONObject) { sb.append(toString((JSONObject)object)); - } else if (object instanceof JSONArray) { - sb.append(toString((JSONArray)object)); + } else if (object instanceof JSONArray) { + sb.append(toString((JSONArray)object)); } else { sb.append(object.toString()); - } - } - } - sb.append('<'); - sb.append('/'); - sb.append(tagName); - sb.append('>'); - } + } + } + } + sb.append('<'); + sb.append('/'); + sb.append(tagName); + sb.append('>'); + } return sb.toString(); } } \ No newline at end of file diff --git a/JSONTokener.java b/JSONTokener.java index f7d8bdf..31525b5 100755 --- a/JSONTokener.java +++ b/JSONTokener.java @@ -36,7 +36,7 @@ SOFTWARE. * it. It is used by the JSONObject and JSONArray constructors to parse * JSON source strings. * @author JSON.org - * @version 2010-12-24 + * @version 2011-11-24 */ public class JSONTokener { @@ -45,7 +45,7 @@ public class JSONTokener { private int index; private int line; private char previous; - private Reader reader; + private final Reader reader; private boolean usePrevious; @@ -55,8 +55,9 @@ public class JSONTokener { * @param reader A reader. */ public JSONTokener(Reader reader) { - this.reader = reader.markSupported() ? - reader : new BufferedReader(reader); + this.reader = reader.markSupported() + ? reader + : new BufferedReader(reader); this.eof = false; this.usePrevious = false; this.previous = 0; @@ -64,13 +65,13 @@ public class JSONTokener { this.character = 1; this.line = 1; } - - + + /** * Construct a JSONTokener from an InputStream. */ public JSONTokener(InputStream inputStream) throws JSONException { - this(new InputStreamReader(inputStream)); + this(new InputStreamReader(inputStream)); } @@ -90,7 +91,7 @@ public class JSONTokener { * the next number or identifier. */ public void back() throws JSONException { - if (usePrevious || index <= 0) { + if (this.usePrevious || this.index <= 0) { throw new JSONException("Stepping back two steps is not supported"); } this.index -= 1; @@ -118,9 +119,9 @@ public class JSONTokener { } return -1; } - + public boolean end() { - return eof && !usePrevious; + return this.eof && !this.usePrevious; } @@ -130,11 +131,11 @@ public class JSONTokener { * @return true if not yet at the end of the source. */ public boolean more() throws JSONException { - next(); - if (end()) { + this.next(); + if (this.end()) { return false; - } - back(); + } + this.back(); return true; } @@ -155,11 +156,11 @@ public class JSONTokener { } catch (IOException exception) { throw new JSONException(exception); } - + if (c <= 0) { // End of stream this.eof = true; c = 0; - } + } } this.index += 1; if (this.previous == '\r') { @@ -184,9 +185,9 @@ public class JSONTokener { * @throws JSONException if the character does not match. */ public char next(char c) throws JSONException { - char n = next(); + char n = this.next(); if (n != c) { - throw syntaxError("Expected '" + c + "' and instead saw '" + + throw this.syntaxError("Expected '" + c + "' and instead saw '" + n + "'"); } return n; @@ -211,9 +212,9 @@ public class JSONTokener { int pos = 0; while (pos < n) { - chars[pos] = next(); - if (end()) { - throw syntaxError("Substring bounds error"); + chars[pos] = this.next(); + if (this.end()) { + throw this.syntaxError("Substring bounds error"); } pos += 1; } @@ -228,7 +229,7 @@ public class JSONTokener { */ public char nextClean() throws JSONException { for (;;) { - char c = next(); + char c = this.next(); if (c == 0 || c > ' ') { return c; } @@ -251,14 +252,14 @@ public class JSONTokener { char c; StringBuffer sb = new StringBuffer(); for (;;) { - c = next(); + c = this.next(); switch (c) { case 0: case '\n': case '\r': - throw syntaxError("Unterminated string"); + throw this.syntaxError("Unterminated string"); case '\\': - c = next(); + c = this.next(); switch (c) { case 'b': sb.append('\b'); @@ -276,7 +277,7 @@ public class JSONTokener { sb.append('\r'); break; case 'u': - sb.append((char)Integer.parseInt(next(4), 16)); + sb.append((char)Integer.parseInt(this.next(4), 16)); break; case '"': case '\'': @@ -285,7 +286,7 @@ public class JSONTokener { sb.append(c); break; default: - throw syntaxError("Illegal escape."); + throw this.syntaxError("Illegal escape."); } break; default: @@ -307,10 +308,10 @@ public class JSONTokener { public String nextTo(char delimiter) throws JSONException { StringBuffer sb = new StringBuffer(); for (;;) { - char c = next(); + char c = this.next(); if (c == delimiter || c == 0 || c == '\n' || c == '\r') { if (c != 0) { - back(); + this.back(); } return sb.toString().trim(); } @@ -329,11 +330,11 @@ public class JSONTokener { char c; StringBuffer sb = new StringBuffer(); for (;;) { - c = next(); + c = this.next(); if (delimiters.indexOf(c) >= 0 || c == 0 || c == '\n' || c == '\r') { if (c != 0) { - back(); + this.back(); } return sb.toString().trim(); } @@ -350,18 +351,18 @@ public class JSONTokener { * @return An object. */ public Object nextValue() throws JSONException { - char c = nextClean(); + char c = this.nextClean(); String string; switch (c) { case '"': case '\'': - return nextString(c); + return this.nextString(c); case '{': - back(); + this.back(); return new JSONObject(this); case '[': - back(); + this.back(); return new JSONArray(this); } @@ -377,13 +378,13 @@ public class JSONTokener { StringBuffer sb = new StringBuffer(); while (c >= ' ' && ",:]}/\\\"[{;=#".indexOf(c) < 0) { sb.append(c); - c = next(); + c = this.next(); } - back(); + this.back(); string = sb.toString().trim(); if (string.equals("")) { - throw syntaxError("Missing value"); + throw this.syntaxError("Missing value"); } return JSONObject.stringToValue(string); } @@ -402,11 +403,11 @@ public class JSONTokener { int startIndex = this.index; int startCharacter = this.character; int startLine = this.line; - reader.mark(Integer.MAX_VALUE); + this.reader.mark(Integer.MAX_VALUE); do { - c = next(); + c = this.next(); if (c == 0) { - reader.reset(); + this.reader.reset(); this.index = startIndex; this.character = startCharacter; this.line = startLine; @@ -417,10 +418,10 @@ public class JSONTokener { throw new JSONException(exc); } - back(); + this.back(); return c; } - + /** * Make a JSONException to signal a syntax error. @@ -429,7 +430,7 @@ public class JSONTokener { * @return A JSONException object, suitable for throwing */ public JSONException syntaxError(String message) { - return new JSONException(message + toString()); + return new JSONException(message + this.toString()); } @@ -439,7 +440,7 @@ public class JSONTokener { * @return " at {index} [character {character} line {line}]" */ public String toString() { - return " at " + index + " [character " + this.character + " line " + + return " at " + this.index + " [character " + this.character + " line " + this.line + "]"; } } \ No newline at end of file diff --git a/JSONWriter.java b/JSONWriter.java index 1a1dd37..855b2bd 100755 --- a/JSONWriter.java +++ b/JSONWriter.java @@ -54,7 +54,7 @@ SOFTWARE. *

* This can sometimes be easier than using a JSONObject to build a string. * @author JSON.org - * @version 2011-11-14 + * @version 2011-11-24 */ public class JSONWriter { private static final int maxdepth = 200; @@ -157,8 +157,9 @@ public class JSONWriter { */ private JSONWriter end(char mode, char c) throws JSONException { if (this.mode != mode) { - throw new JSONException(mode == 'a' ? "Misplaced endArray." : - "Misplaced endObject."); + throw new JSONException(mode == 'a' + ? "Misplaced endArray." + : "Misplaced endObject."); } this.pop(mode); try { @@ -259,8 +260,11 @@ public class JSONWriter { throw new JSONException("Nesting error."); } this.top -= 1; - this.mode = this.top == 0 ? - 'd' : this.stack[this.top - 1] == null ? 'a' : 'k'; + this.mode = this.top == 0 + ? 'd' + : this.stack[this.top - 1] == null + ? 'a' + : 'k'; } /**