/** * Construct a JSONArray from a JSONTokener. * * @param x A JSONTokener * @throws JSONException If there is a syntax error. */ public JSONArray(JSONTokener x) throws JSONException { this(); if (x.nextClean() != '[') { throw x.syntaxError("A JSONArray text must start with '['"); } if (x.nextClean() != ']') { x.back(); for (; ; ) { if (x.nextClean() == ',') { x.back(); this.myArrayList.add(JSONObject.NULL); } else { x.back(); this.myArrayList.add(x.nextValue()); } switch (x.nextClean()) { case ';': case ',': if (x.nextClean() == ']') { return; } x.back(); break; case ']': return; default: throw x.syntaxError("Expected a ',' or ']'"); } } } }
/** * Construct a JSONObject from a JSONTokener. * * @param x A JSONTokener object containing the source string. * @throws JSONException If there is a syntax error in the source string or a duplicated key. */ public JSONObject(JSONTokener x) throws JSONException { this(); char c; String key; if (x.nextClean() != '{') { throw x.syntaxError("A JSONObject text must begin with '{'"); } for (; ; ) { c = x.nextClean(); switch (c) { case 0: throw x.syntaxError("A JSONObject text must end with '}'"); case '}': return; default: x.back(); key = x.nextValue().toString(); } /* * The key is followed by ':'. We will also tolerate '=' or '=>'. */ c = x.nextClean(); if (c == '=') { if (x.next() != '>') { x.back(); } } else if (c != ':') { throw x.syntaxError("Expected a ':' after a key"); } putOnce(key, x.nextValue()); /* * Pairs are separated by ','. We will also tolerate ';'. */ switch (x.nextClean()) { case ';': case ',': if (x.nextClean() == '}') { return; } x.back(); break; case '}': return; default: throw x.syntaxError("Expected a ',' or '}'"); } } }
/** * Determine if the source string still contains characters that next() can consume. * * @return true if not yet at the end of the source. */ public boolean more() throws JSONException { next(); if (end()) { return false; } back(); return true; }
/** * Construct a JSONArray from a JSONTokener. * * @param x A JSONTokener * @throws JSONException If there is a syntax error. */ @SuppressWarnings("unchecked") public JSONArray(JSONTokener x) throws JSONException { this(); char c = x.nextClean(); char q; if (c == '[') { q = ']'; } else if (c == '(') { q = ')'; } else { throw x.syntaxError("A JSONArray text must start with '['"); } if (x.nextClean() == ']') { return; } x.back(); for (; ; ) { if (x.nextClean() == ',') { x.back(); this.myArrayList.add(null); } else { x.back(); this.myArrayList.add(x.nextValue()); } c = x.nextClean(); switch (c) { case ';': case ',': if (x.nextClean() == ']') { return; } x.back(); break; case ']': case ')': if (q != c) { throw x.syntaxError("Expected a '" + new Character(q) + "'"); } return; default: throw x.syntaxError("Expected a ',' or ']'"); } } }
/** * Get the next value. The value can be a Boolean, Double, Integer, JSONArray, JSONObject, Long, * or String, or the JSONObject.NULL object. * * @throws JSONException If syntax error. * @return An object. */ public Object nextValue() throws JSONException { char c = nextClean(); String s; switch (c) { case '"': case '\'': return nextString(c); case '{': back(); return new JSONObject(this); case '[': case '(': back(); return new JSONArray(this); } /* * Handle unquoted text. This could be the values true, false, or null, * or it can be a number. An implementation (such as this one) is * allowed to also accept non-standard forms. * * Accumulate characters until we reach the end of the text or a * formatting character. */ StringBuffer sb = new StringBuffer(); while (c >= ' ' && ",:]}/\\\"[{;=#".indexOf(c) < 0) { sb.append(c); c = next(); } back(); s = sb.toString().trim(); if (s.equals("")) { throw syntaxError("Missing value"); } return JSONObject.stringToValue(s); }
/** * Get the text up but not including the specified character or the end of line, whichever comes * first. * * @param d A delimiter character. * @return A string. */ public String nextTo(char d) throws JSONException { StringBuffer sb = new StringBuffer(); for (; ; ) { char c = next(); if (c == d || c == 0 || c == '\n' || c == '\r') { if (c != 0) { back(); } return sb.toString().trim(); } sb.append(c); } }
/** * Get the text up but not including one of the specified delimiter characters or the end of line, * whichever comes first. * * @param delimiters A set of delimiter characters. * @return A string, trimmed. */ public String nextTo(String delimiters) throws JSONException { char c; StringBuffer sb = new StringBuffer(); for (; ; ) { c = next(); if (delimiters.indexOf(c) >= 0 || c == 0 || c == '\n' || c == '\r') { if (c != 0) { back(); } return sb.toString().trim(); } sb.append(c); } }
/** * Skip characters until the next character is the requested character. If the requested character * is not found, no characters are skipped. * * @param to A character to skip to. * @return The requested character, or zero if the requested character is not found. */ public char skipTo(char to) throws JSONException { char c; try { int startIndex = this.index; int startCharacter = this.character; int startLine = this.line; reader.mark(Integer.MAX_VALUE); do { c = next(); if (c == 0) { reader.reset(); this.index = startIndex; this.character = startCharacter; this.line = startLine; return c; } } while (c != to); } catch (IOException exc) { throw new JSONException(exc); } back(); return c; }
/** * Parse all the vertices from the JSON retreived from Rexster. Inspired by the implementation of * the JSONObject class. * * @param br buffer over the HTTP response content * @return JSONTokener tokener over the HTTP JSON. Null in case the results array is empty. */ public static JSONTokener parseJSONEnvelope(BufferedReader br) throws InterruptedException { JSONTokener tokener = null; try { tokener = new JSONTokener(br); /* check that the JSON is well-formed by starting with a '{' */ if (tokener.nextClean() != START_OBJECT) { LOG.error(String.format("A JSONObject text must begin with '%c'", START_OBJECT)); } /* loop on the whole array */ char c = '\0'; String key = null; for (; ; ) { c = tokener.nextClean(); switch (c) { case 0: LOG.error(String.format("A JSONObject text must end with '%c'", END_OBJECT)); break; case END_OBJECT: return tokener; default: tokener.back(); key = tokener.nextValue().toString(); } c = tokener.nextClean(); if (c != KEY_VALUE_SEPARATOR) { LOG.error(String.format("Expected a %c after a key", c)); } if (key != null && !key.equals("results")) { tokener.nextValue(); } else { /* starting array */ c = tokener.nextClean(); if (c != START_ARRAY) { LOG.error("'results' is expected to be an array"); } /* check if the array is emty. If so, return null to signal that no objects are available in the array, otherwise return the tokener. */ c = tokener.nextClean(); if (c == END_ARRAY) { return null; } else { tokener.back(); return tokener; } } switch (tokener.nextClean()) { case ';': case ',': if (tokener.nextClean() == '}') { return tokener; } tokener.back(); break; case '}': return tokener; default: LOG.error("Expected a ',' or '}'"); } } } catch (JSONException e) { LOG.error("Unable to parse the JSON with the vertices.\n" + e.getMessage()); throw new InterruptedException(e.toString()); } }