public Token next(boolean skipWhitespace) { int from = reader.position(); int ch = read(); switch (ch) { case '{': token = Token.create(Token.Type.OBJECT_START, reader, from, reader.position()); break; case '}': token = Token.create(Token.Type.OBJECT_END, reader, from, reader.position()); break; case '[': token = Token.create(Token.Type.ARRAY_START, reader, from, reader.position()); break; case ']': token = Token.create(Token.Type.ARRAY_END, reader, from, reader.position()); break; case ':': token = Token.create(Token.Type.COLON, reader, from, reader.position()); break; case ',': token = Token.create(Token.Type.COMMA, reader, from, reader.position()); break; default: if (isWhitespaceStart(ch)) { readWhitespace(); token = Token.create(Token.Type.WS, reader, from, reader.position()); } else if (isStringStart(ch)) { readString(); token = Token.create(Token.Type.STRING, reader, from, reader.position()); } else if (isNullStart(ch)) { readNull(); token = Token.create(Token.Type.NULL, reader, from, reader.position()); } else if (isTrueStart(ch)) { readTrue(); token = Token.create(Token.Type.TRUE, reader, from, reader.position()); } else if (isFalseStart(ch)) { readFalse(); token = Token.create(Token.Type.FALSE, reader, from, reader.position()); } else if (isNumberStart(ch)) { readNumber(); token = Token.create(Token.Type.NUMBER, reader, from, reader.position()); } else if (ch == -1) { token = Token.create(Token.Type.EOF, reader, from, reader.position()); } else { throw new RuntimeException("Invalid Json Data\n" + reader.toString()); } } while (skipWhitespace && Token.Type.WS.equals(token.type)) { token = next(); } return token; }