/** * Reads a JSON value from the given reader. * <p> * Characters are read in chunks and buffered internally, therefore wrapping an existing reader in * an additional <code>BufferedReader</code> does <strong>not</strong> improve reading * performance. * </p> * * @param reader the reader to read the JSON value from * @return the JSON value that has been read * @throws IOException if an I/O error occurs in the reader * @throws ParseException if the input is not valid JSON */ public static JsonValue readJSON(Reader reader) throws IOException { return new JsonParser(reader).parse(); }
JsonValue parse() throws IOException { read(); skipWhiteSpace(); JsonValue result=readValue(); skipWhiteSpace(); if (!isEndOfText()) throw error("Unexpected character"); return result; }
private ParseException expected(String expected) { if (isEndOfText()) { return error("Unexpected end of input"); } return error("Expected "+expected); }
private JsonArray readArray() throws IOException { read(); JsonArray array=new JsonArray(); skipWhiteSpace(); if (readIf(']')) { return array; } do { skipWhiteSpace(); array.add(readValue()); skipWhiteSpace(); } while (readIf(',')); if (!readIf(']')) { throw expected("',' or ']'"); } return array; }
private JsonValue readValue() throws IOException { switch(current) { case 'n': return readNull(); case 't': return readTrue(); case 'f': return readFalse(); case '"': return readString(); case '[': return readArray(); case '{': return readObject(); case '-': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': return readNumber(); default: throw expected("value"); } }
private JsonValue readNumber() throws IOException { startCapture(); readIf('-'); int firstDigit=current; if (!readDigit()) { throw expected("digit"); } if (firstDigit!='0') { while (readDigit()) { } } readFraction(); readExponent(); return new JsonNumber(Double.parseDouble(endCapture())); }
private String readStringInternal() throws IOException { read(); startCapture(); while (current!='"') { if (current=='\\') { pauseCapture(); readEscape(); startCapture(); } else if (current<0x20) { throw expected("valid string character"); } else { read(); } } String string=endCapture(); read(); return string; }
private void skipWhiteSpace() throws IOException { while (isWhiteSpace()) { read(); } }
private String readName() throws IOException { if (current!='"') { throw expected("name"); } return readStringInternal(); }
private ParseException error(String message) { int absIndex=bufferOffset+index; int column=absIndex-lineOffset; int offset=isEndOfText() ? absIndex : absIndex-1; return new ParseException(message, offset, line, column-1); }
private JsonArray readArray() throws IOException { read(); JsonArray array=new JsonArray(); skipWhiteSpace(); if (readIf(']')) { return array; } do { skipWhiteSpace(); array.add(readValue()); skipWhiteSpace(); } while (readIf(',')); if (!readIf(']')) { throw expected("',' or ']'"); } return array; }
private JsonValue readValue() throws IOException { switch(current) { case 'n': return readNull(); case 't': return readTrue(); case 'f': return readFalse(); case '"': return readString(); case '[': return readArray(); case '{': return readObject(); case '-': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': return readNumber(); default: throw expected("value"); } }
private JsonValue readNumber() throws IOException { startCapture(); readIf('-'); int firstDigit=current; if (!readDigit()) { throw expected("digit"); } if (firstDigit!='0') { while (readDigit()) { } } readFraction(); readExponent(); return new JsonNumber(Double.parseDouble(endCapture())); }
private String readStringInternal() throws IOException { read(); startCapture(); while (current!='"') { if (current=='\\') { pauseCapture(); readEscape(); startCapture(); } else if (current<0x20) { throw expected("valid string character"); } else { read(); } } String string=endCapture(); read(); return string; }