static { START_DOCUMENT.transition(JsonToken.CURLYOPEN, START_OBJECT); START_DOCUMENT.transition(JsonToken.SQUAREOPEN, START_ARRAY); START_OBJECT.transition(JsonToken.CURLYCLOSE, END_OBJECT); START_OBJECT.transition(JsonToken.STRING, KEY); KEY.transition(JsonToken.COLON, COLON); COLON.transition(JsonToken.STRING, OBJECT_STRING); COLON.transition(JsonToken.NUMBER, OBJECT_NUMBER); COLON.transition(JsonToken.TRUE, OBJECT_TRUE); COLON.transition(JsonToken.FALSE, OBJECT_FALSE); COLON.transition(JsonToken.NULL, OBJECT_NULL); COLON.transition(JsonToken.CURLYOPEN, START_OBJECT); COLON.transition(JsonToken.SQUAREOPEN, START_ARRAY); OBJECT_STRING.transition(JsonToken.CURLYCLOSE, END_OBJECT); OBJECT_STRING.transition(JsonToken.COMMA, OBJECT_COMMA); OBJECT_NUMBER.transition(JsonToken.CURLYCLOSE, END_OBJECT); OBJECT_NUMBER.transition(JsonToken.COMMA, OBJECT_COMMA); OBJECT_TRUE.transition(JsonToken.CURLYCLOSE, END_OBJECT); OBJECT_TRUE.transition(JsonToken.COMMA, OBJECT_COMMA); OBJECT_FALSE.transition(JsonToken.CURLYCLOSE, END_OBJECT); OBJECT_FALSE.transition(JsonToken.COMMA, OBJECT_COMMA); OBJECT_NULL.transition(JsonToken.CURLYCLOSE, END_OBJECT); OBJECT_NULL.transition(JsonToken.COMMA, OBJECT_COMMA); OBJECT_COMMA.transition(JsonToken.STRING, KEY); END_OBJECT.transition(JsonToken.CURLYCLOSE, END_OBJECT); END_OBJECT.transition(JsonToken.SQUARECLOSE, END_ARRAY); // Need an enclosing scope to determine the next state // END_OBJECT.transition(JsonToken.COMMA, OBJECT_COMMA or ARRAY_COMMA ); END_OBJECT.transition(JsonToken.EOF, END_DOCUMENT); START_ARRAY.transition(JsonToken.STRING, ARRAY_STRING); START_ARRAY.transition(JsonToken.NUMBER, ARRAY_NUMBER); START_ARRAY.transition(JsonToken.TRUE, ARRAY_TRUE); START_ARRAY.transition(JsonToken.FALSE, ARRAY_FALSE); START_ARRAY.transition(JsonToken.NULL, ARRAY_NULL); START_ARRAY.transition(JsonToken.CURLYOPEN, START_OBJECT); START_ARRAY.transition(JsonToken.SQUAREOPEN, START_ARRAY); START_ARRAY.transition(JsonToken.SQUARECLOSE, END_ARRAY); ARRAY_STRING.transition(JsonToken.COMMA, ARRAY_COMMA); ARRAY_STRING.transition(JsonToken.SQUARECLOSE, END_ARRAY); ARRAY_NUMBER.transition(JsonToken.COMMA, ARRAY_COMMA); ARRAY_NUMBER.transition(JsonToken.SQUARECLOSE, END_ARRAY); ARRAY_TRUE.transition(JsonToken.COMMA, ARRAY_COMMA); ARRAY_TRUE.transition(JsonToken.SQUARECLOSE, END_ARRAY); ARRAY_FALSE.transition(JsonToken.COMMA, ARRAY_COMMA); ARRAY_FALSE.transition(JsonToken.SQUARECLOSE, END_ARRAY); ARRAY_NULL.transition(JsonToken.COMMA, ARRAY_COMMA); ARRAY_NULL.transition(JsonToken.SQUARECLOSE, END_ARRAY); ARRAY_COMMA.transition(JsonToken.STRING, ARRAY_STRING); ARRAY_COMMA.transition(JsonToken.NUMBER, ARRAY_NUMBER); ARRAY_COMMA.transition(JsonToken.TRUE, ARRAY_TRUE); ARRAY_COMMA.transition(JsonToken.FALSE, ARRAY_FALSE); ARRAY_COMMA.transition(JsonToken.NULL, ARRAY_NULL); ARRAY_COMMA.transition(JsonToken.CURLYOPEN, START_OBJECT); ARRAY_COMMA.transition(JsonToken.SQUAREOPEN, START_ARRAY); END_ARRAY.transition(JsonToken.CURLYCLOSE, END_OBJECT); END_ARRAY.transition(JsonToken.SQUARECLOSE, END_ARRAY); // Need an enclosing scope to determine the next state // END_ARRAY.transition(JsonToken.COMMA, OBJECT_COMMA or ARRAY_COMMA); END_ARRAY.transition(JsonToken.EOF, END_DOCUMENT); }
/** * Parses an object from the lexer * * @param lexer the lexer * @return a Map representing a JSON object */ private Map parseObject(JsonLexer lexer) { Map content = new HashMap(); JsonToken previousToken = null; JsonToken currentToken = null; for (; ; ) { currentToken = lexer.nextToken(); if (currentToken == null) { throw new JsonException( "Expected a String key on line: " + lexer.getReader().getLine() + ", " + "column: " + lexer.getReader().getColumn() + ".\n" + "But got an unterminated object."); } // expect a string key, or already a closing curly brace if (currentToken.getType() == CLOSE_CURLY) { return content; } else if (currentToken.getType() != STRING) { throw new JsonException( "Expected " + STRING.getLabel() + " key " + "on line: " + currentToken.getStartLine() + ", " + "column: " + currentToken.getStartColumn() + ".\n" + "But got '" + currentToken.getText() + "' instead."); } String mapKey = (String) currentToken.getValue(); currentToken = lexer.nextToken(); if (currentToken == null) { throw new JsonException( "Expected a " + COLON.getLabel() + " " + "on line: " + lexer.getReader().getLine() + ", " + "column: " + lexer.getReader().getColumn() + ".\n" + "But got an unterminated object."); } // expect a colon between the key and value pair if (currentToken.getType() != COLON) { throw new JsonException( "Expected " + COLON.getLabel() + " " + "on line: " + currentToken.getStartLine() + ", " + "column: " + currentToken.getStartColumn() + ".\n" + "But got '" + currentToken.getText() + "' instead."); } currentToken = lexer.nextToken(); if (currentToken == null) { throw new JsonException( "Expected a value " + "on line: " + lexer.getReader().getLine() + ", " + "column: " + lexer.getReader().getColumn() + ".\n" + "But got an unterminated object."); } // value can be an object, an array, a number, string, boolean or null values if (currentToken.getType() == OPEN_CURLY) { content.put(mapKey, parseObject(lexer)); } else if (currentToken.getType() == OPEN_BRACKET) { content.put(mapKey, parseArray(lexer)); } else if (currentToken.getType().ordinal() >= NULL.ordinal()) { content.put(mapKey, currentToken.getValue()); } else { throw new JsonException( "Expected a value, an array, or an object " + "on line: " + currentToken.getStartLine() + ", " + "column: " + currentToken.getStartColumn() + ".\n" + "But got '" + currentToken.getText() + "' instead."); } previousToken = currentToken; currentToken = lexer.nextToken(); // premature end of the object if (currentToken == null) { throw new JsonException( "Expected " + CLOSE_CURLY.getLabel() + " or " + COMMA.getLabel() + " " + "on line: " + previousToken.getEndLine() + ", " + "column: " + previousToken.getEndColumn() + ".\n" + "But got an unterminated object."); } // Expect a comma for an upcoming key/value pair // or a closing curly brace for the end of the object if (currentToken.getType() == CLOSE_CURLY) { break; } else if (currentToken.getType() != COMMA) { throw new JsonException( "Expected a value or " + CLOSE_CURLY.getLabel() + " " + "on line: " + currentToken.getStartLine() + ", " + "column: " + currentToken.getStartColumn() + ".\n" + "But got '" + currentToken.getText() + "' instead."); } } return content; }