in tooling/camel-util-json/src/main/java/org/apache/camel/util/json/Jsoner.java [154:376]
private static JsonArray deserialize(final Reader deserializable, final Set<DeserializationOptions> flags)
throws DeserializationException, IOException {
final Yylex lexer = new Yylex(deserializable);
Yytoken token;
States currentState;
int returnCount = 1;
final LinkedList<States> stateStack = new LinkedList<>();
final LinkedList<Object> valueStack = new LinkedList<>();
stateStack.addLast(States.INITIAL);
do {
/* Parse through the parsable string's tokens. */
currentState = Jsoner.popNextState(stateStack);
token = Jsoner.lexNextToken(lexer);
switch (currentState) {
case DONE:
/* The parse has finished a JSON value. */
if (!flags.contains(DeserializationOptions.ALLOW_CONCATENATED_JSON_VALUES)
|| Yytoken.Types.END.equals(token.getType())) {
/*
* Break if concatenated values are not allowed or if an END
* token is read.
*/
break;
}
/*
* Increment the amount of returned JSON values and treat the
* token as if it were a fresh parse.
*/
returnCount += 1;
/* Fall through to the case for the initial state. */
//$FALL-THROUGH$
case INITIAL:
/* The parse has just started. */
switch (token.getType()) {
case DATUM:
/* A boolean, null, Number, or String could be detected. */
if (flags.contains(DeserializationOptions.ALLOW_JSON_DATA)) {
valueStack.addLast(token.getValue());
stateStack.addLast(States.DONE);
} else {
throw new DeserializationException(
lexer.getPosition(), DeserializationException.Problems.DISALLOWED_TOKEN, token);
}
break;
case LEFT_BRACE:
/* An object is detected. */
if (flags.contains(DeserializationOptions.ALLOW_JSON_OBJECTS)) {
valueStack.addLast(new JsonObject());
stateStack.addLast(States.PARSING_OBJECT);
} else {
throw new DeserializationException(
lexer.getPosition(), DeserializationException.Problems.DISALLOWED_TOKEN, token);
}
break;
case LEFT_SQUARE:
/* An array is detected. */
if (flags.contains(DeserializationOptions.ALLOW_JSON_ARRAYS)) {
valueStack.addLast(new JsonArray());
stateStack.addLast(States.PARSING_ARRAY);
} else {
throw new DeserializationException(
lexer.getPosition(), DeserializationException.Problems.DISALLOWED_TOKEN, token);
}
break;
default:
/* Neither a JSON array or object was detected. */
throw new DeserializationException(
lexer.getPosition(), DeserializationException.Problems.UNEXPECTED_TOKEN, token);
}
break;
case PARSED_ERROR:
/*
* The parse could be in this state due to the state stack not
* having a state to pop off.
*/
throw new DeserializationException(
lexer.getPosition(), DeserializationException.Problems.UNEXPECTED_TOKEN, token);
case PARSING_ARRAY:
switch (token.getType()) {
case COMMA:
/*
* The parse could detect a comma while parsing an array
* since it separates each element.
*/
stateStack.addLast(currentState);
break;
case DATUM:
/* The parse found an element of the array. */
JsonArray val = (JsonArray) valueStack.getLast();
val.add(token.getValue());
stateStack.addLast(currentState);
break;
case LEFT_BRACE:
/* The parse found an object in the array. */
val = (JsonArray) valueStack.getLast();
final JsonObject object = new JsonObject();
val.add(object);
valueStack.addLast(object);
stateStack.addLast(currentState);
stateStack.addLast(States.PARSING_OBJECT);
break;
case LEFT_SQUARE:
/* The parse found another array in the array. */
val = (JsonArray) valueStack.getLast();
final JsonArray array = new JsonArray();
val.add(array);
valueStack.addLast(array);
stateStack.addLast(currentState);
stateStack.addLast(States.PARSING_ARRAY);
break;
case RIGHT_SQUARE:
/* The parse found the end of the array. */
if (valueStack.size() > returnCount) {
valueStack.removeLast();
} else {
/* The parse has been fully resolved. */
stateStack.addLast(States.DONE);
}
break;
default:
/* Any other token is invalid in an array. */
throw new DeserializationException(
lexer.getPosition(), DeserializationException.Problems.UNEXPECTED_TOKEN, token);
}
break;
case PARSING_OBJECT:
/* The parse has detected the start of an object. */
switch (token.getType()) {
case COMMA:
/*
* The parse could detect a comma while parsing an object
* since it separates each key value pair. Continue parsing
* the object.
*/
stateStack.addLast(currentState);
break;
case DATUM:
/* The token ought to be a key. */
if (token.getValue() instanceof String) {
/*
* JSON keys are always strings, strings are not always
* JSON keys but it is going to be treated as one.
* Continue parsing the object.
*/
final String key = (String) token.getValue();
valueStack.addLast(key);
stateStack.addLast(currentState);
stateStack.addLast(States.PARSING_ENTRY);
} else {
/*
* Abort! JSON keys are always strings and it wasn't a
* string.
*/
throw new DeserializationException(
lexer.getPosition(), DeserializationException.Problems.UNEXPECTED_TOKEN, token);
}
break;
case RIGHT_BRACE:
/* The parse has found the end of the object. */
if (valueStack.size() > returnCount) {
/* There are unresolved values remaining. */
valueStack.removeLast();
} else {
/* The parse has been fully resolved. */
stateStack.addLast(States.DONE);
}
break;
default:
/* The parse didn't detect the end of an object or a key. */
throw new DeserializationException(
lexer.getPosition(), DeserializationException.Problems.UNEXPECTED_TOKEN, token);
}
break;
case PARSING_ENTRY:
switch (token.getType()) {
/* Parsed pair keys can only happen while parsing objects. */
case COLON:
/*
* The parse could detect a colon while parsing a key value
* pair since it separates the key and value from each
* other. Continue parsing the entry.
*/
stateStack.addLast(currentState);
break;
case DATUM:
/* The parse has found a value for the parsed pair key. */
String key = (String) valueStack.removeLast();
JsonObject parent = (JsonObject) valueStack.getLast();
parent.put(key, token.getValue());
break;
case LEFT_BRACE:
/* The parse has found an object for the parsed pair key. */
key = (String) valueStack.removeLast();
parent = (JsonObject) valueStack.getLast();
final JsonObject object = new JsonObject();
parent.put(key, object);
valueStack.addLast(object);
stateStack.addLast(States.PARSING_OBJECT);
break;
case LEFT_SQUARE:
/* The parse has found an array for the parsed pair key. */
key = (String) valueStack.removeLast();
parent = (JsonObject) valueStack.getLast();
final JsonArray array = new JsonArray();
parent.put(key, array);
valueStack.addLast(array);
stateStack.addLast(States.PARSING_ARRAY);
break;
default:
/*
* The parse didn't find anything for the parsed pair key.
*/
throw new DeserializationException(
lexer.getPosition(), DeserializationException.Problems.UNEXPECTED_TOKEN, token);
}
break;
default:
break;
}
/* If we're not at the END and DONE then do the above again. */
} while (!(States.DONE.equals(currentState) && Yytoken.Types.END.equals(token.getType())));
return new JsonArray(valueStack);
}