Skip to content

io_nats_jparse_parser_event

Rick Hightower edited this page Jul 18, 2023 · 1 revision

io.nats.jparse.parser.event

class diagram

JsonEventFastParser

The JsonEventFastParser class is a public class that extends the JsonEventAbstractParser. It is a fast JSON event parser.

@Override

public void parseWithEvents(CharSource source, final TokenEventListener event)

@Override
public void parseWithEvents(CharSource source, final TokenEventListener event) {
    int ch = source.nextSkipWhiteSpace();
    switch(ch) {
        case OBJECT_START_TOKEN:
            parseObject(source, event);
            break;
        case ARRAY_START_TOKEN:
            parseArray(source, event);
            break;
        case TRUE_BOOLEAN_START:
            parseTrue(source, event);
            break;
        case FALSE_BOOLEAN_START:
            parseFalse(source, event);
            break;
        case NULL_START:
            parseNull(source, event);
            break;
        case STRING_START_TOKEN:
            parseString(source, event);
            break;
        case NUM_0:
        case NUM_1:
        case NUM_2:
        case NUM_3:
        case NUM_4:
        case NUM_5:
        case NUM_6:
        case NUM_7:
        case NUM_8:
        case NUM_9:
        case MINUS:
        case PLUS:
            parseNumber(source, event);
            break;
        default:
            throw new UnexpectedCharacterException("Scanning JSON", "Unexpected character", source, (char) ch);
    }
}

The parseWithEvents method in the JsonEventFastParser class is used to parse JSON content with event callbacks. Here is a step-by-step description of what this method does:

  1. It takes two parameters: source, which is a CharSource object representing the JSON content to parse, and event, which is a TokenEventListener object that will receive the parsing events.

  2. The method calls source.nextSkipWhiteSpace() to read the next character from the source and skips any leading white spaces. The returned value is stored in the ch variable.

  3. It enters a switch statement based on the value of ch.

  4. If ch equals OBJECT_START_TOKEN, the method calls the parseObject method, passing the source and event parameters. This method is responsible for parsing JSON objects.

  5. If ch equals ARRAY_START_TOKEN, the method calls the parseArray method, passing the source and event parameters. This method is responsible for parsing JSON arrays.

  6. If ch equals TRUE_BOOLEAN_START, the method calls the parseTrue method, passing the source and event parameters. This method is responsible for parsing the JSON "true" boolean value.

  7. If ch equals FALSE_BOOLEAN_START, the method calls the parseFalse method, passing the source and event parameters. This method is responsible for parsing the JSON "false" boolean value.

  8. If ch equals NULL_START, the method calls the parseNull method, passing the source and event parameters. This method is responsible for parsing the JSON "null" value.

  9. If ch equals STRING_START_TOKEN, the method calls the parseString method, passing the source and event parameters. This method is responsible for parsing JSON strings.

  10. If ch equals any of the number-related characters (NUM_0, NUM_1, NUM_2, etc.), the method calls the parseNumber method, passing the source and event parameters. This method is responsible for parsing JSON numeric values.

  11. If none of the above cases match, it means that an unexpected character was encountered, and the method throws an UnexpectedCharacterException, passing a message, the current source, and the unexpected character.

Overall, the parseWithEvents method determines the type of JSON value based on the first character of the input source, and then delegates the parsing to specific methods accordingly. It ensures that the appropriate parsing method is called based on the type of JSON token encountered, and if an unexpected character is encountered, it throws an exception.

The method parseWithEvents in the JsonEventFastParser class is used to parse a JSON input using an event-based approach. It takes a CharSource object representing the input source and a TokenEventListener object to handle the parsing events.

Within the method, it reads the first character from the input source and determines the type of token it represents. Based on the token, the method dispatches the parsing task to corresponding methods such as parseObject, parseArray, parseTrue, parseFalse, parseNull, parseString, or parseNumber.

If the first character does not match any of the expected JSON tokens, it throws an exception indicating an unexpected character.

Overall, this method enables parsing of JSON input using event-based parsing technique, where the parser notifies the listener about different events encountered during parsing, such as the start and end of JSON objects or arrays, the discovery of boolean values, null values, strings, or numeric values.

sequence diagram

private void parseArray(final CharSource source, final TokenEventListener event)

private void parseArray(final CharSource source, final TokenEventListener event) {
    event.start(TokenTypes.ARRAY_TOKEN, source.getIndex(), source);
    boolean done = false;
    while (!done) {
        done = parseArrayItem(source, event);
        if (!done) {
            done = source.findCommaOrEndForArray();
        }
    }
    event.end(TokenTypes.ARRAY_TOKEN, source.getIndex(), source);
}

The parseArray method in the JsonEventFastParser class is responsible for parsing JSON arrays. Here is a step-by-step breakdown of what this method does:

  1. The method takes two arguments: source, which is a CharSource object representing the source of the JSON data, and event, which is a TokenEventListener object used for notifying events during parsing.

  2. The method starts by calling the start method of the event object to notify the start of an array token, providing the token type, the index of the source, and the source itself.

  3. A boolean variable done is initialized to false, indicating the parsing process is not yet completed.

  4. The method enters a while loop that continues until the parsing is complete (indicated by done being set to true).

  5. Inside the loop, the method calls the parseArrayItem method to parse each item in the array. This method is responsible for handling the inner elements of the array and returns a boolean value indicating whether the parsing for the item is complete or not.

  6. If the parsing for the current item is not complete (indicated by the returned value of parseArrayItem being false), the method calls the findCommaOrEndForArray method of the source object. This method is responsible for finding the next comma separator or the end of the array in the source and returns a boolean value indicating whether the parsing for the array is complete or not.

  7. The while loop continues or terminates based on the value of done. If done is true, the parsing is complete, and the loop will exit.

  8. Finally, the method calls the end method of the event object to notify the end of the array token, providing the token type, the index of the source, and the source itself.

This method essentially iterates over the elements of a JSON array, calling the appropriate parsing methods and notifying the events to the TokenEventListener during the process.

The parseArray method in the JsonEventFastParser class is used to parse an array from a given input source and notify the provided TokenEventListener of the encountered array tokens.

The method starts by calling the start method of the TokenEventListener to notify the start of the array token.

Then, it enters a loop to parse each item in the array. It calls the parseArrayItem method to parse each item, and if the parsing is not yet done, it checks if there is a comma (,) or end (]) of the array.

Once the parsing is done, it calls the end method of the TokenEventListener to notify the end of the array token.

sequence diagram

private boolean parseArrayItem(CharSource source, final TokenEventListener event)

private boolean parseArrayItem(CharSource source, final TokenEventListener event) {
    char startChar = source.getCurrentChar();
    int ch = source.nextSkipWhiteSpace();
    switch(ch) {
        case OBJECT_START_TOKEN:
            event.start(TokenTypes.ARRAY_ITEM_TOKEN, source.getIndex(), source);
            parseObject(source, event);
            event.end(TokenTypes.ARRAY_ITEM_TOKEN, source.getIndex(), source);
            break;
        case ARRAY_START_TOKEN:
            event.start(TokenTypes.ARRAY_ITEM_TOKEN, source.getIndex(), source);
            parseArray(source, event);
            event.end(TokenTypes.ARRAY_ITEM_TOKEN, source.getIndex(), source);
            break;
        case TRUE_BOOLEAN_START:
            event.start(TokenTypes.ARRAY_ITEM_TOKEN, source.getIndex(), source);
            parseTrue(source, event);
            event.end(TokenTypes.ARRAY_ITEM_TOKEN, source.getIndex(), source);
            break;
        case FALSE_BOOLEAN_START:
            event.start(TokenTypes.ARRAY_ITEM_TOKEN, source.getIndex(), source);
            parseFalse(source, event);
            event.end(TokenTypes.ARRAY_ITEM_TOKEN, source.getIndex(), source);
            break;
        case NULL_START:
            event.start(TokenTypes.ARRAY_ITEM_TOKEN, source.getIndex(), source);
            parseNull(source, event);
            event.end(TokenTypes.ARRAY_ITEM_TOKEN, source.getIndex(), source);
            break;
        case STRING_START_TOKEN:
            event.start(TokenTypes.ARRAY_ITEM_TOKEN, source.getIndex(), source);
            parseString(source, event);
            event.end(TokenTypes.ARRAY_ITEM_TOKEN, source.getIndex(), source);
            break;
        case NUM_0:
        case NUM_1:
        case NUM_2:
        case NUM_3:
        case NUM_4:
        case NUM_5:
        case NUM_6:
        case NUM_7:
        case NUM_8:
        case NUM_9:
        case MINUS:
        case PLUS:
            event.start(TokenTypes.ARRAY_ITEM_TOKEN, source.getIndex(), source);
            parseNumber(source, event);
            event.end(TokenTypes.ARRAY_ITEM_TOKEN, source.getIndex(), source);
            if (source.getCurrentChar() == ARRAY_END_TOKEN || source.getCurrentChar() == ARRAY_SEP) {
                if (source.getCurrentChar() == ARRAY_END_TOKEN) {
                    source.next();
                    return true;
                }
            }
            break;
        case ARRAY_END_TOKEN:
            if (startChar == ARRAY_SEP) {
                throw new UnexpectedCharacterException("Parsing Array Item", "Trailing comma", source, (char) ch);
            }
            source.next();
            return true;
        default:
            throw new UnexpectedCharacterException("Parsing Array Item", "Unexpected character", source, (char) ch);
    }
    return false;
}

The parseArrayItem method is responsible for parsing an item within a JSON array. Here is a step-by-step description of what this method does based on its body:

  1. The method takes two parameters: a CharSource object, which represents the source of characters to be parsed, and a TokenEventListener object, which handles the parsing events.

  2. The method starts by getting the current character from the CharSource and storing it in the startChar variable. It then calls the nextSkipWhiteSpace method on the CharSource to get the next non-whitespace character and stores it in the ch variable.

  3. The method performs a switch statement on the value of ch to determine the type of JSON value to be parsed:

    • If ch is equal to OBJECT_START_TOKEN, it means that the item is an object. The method calls the start method on the TokenEventListener to indicate the start of an array item, followed by invoking the parseObject method to parse the nested object. After parsing the object, the end method is called on the TokenEventListener to indicate the end of the array item.

    • If ch is equal to ARRAY_START_TOKEN, it means that the item is an array. The method follows the same steps as described for the object case, but calls the parseArray method instead to parse the nested array.

    • If ch is equal to TRUE_BOOLEAN_START, it means that the item is a boolean value true. The method follows the same steps as described for the object case, but calls the parseTrue method instead to parse the value true.

    • If ch is equal to FALSE_BOOLEAN_START, it means that the item is a boolean value false. The method follows the same steps as described for the object case, but calls the parseFalse method instead to parse the value false.

    • If ch is equal to NULL_START, it means that the item is a null value. The method follows the same steps as described for the object case, but calls the parseNull method instead to parse the value null.

    • If ch is equal to STRING_START_TOKEN, it means that the item is a string value. The method follows the same steps as described for the object case, but calls the parseString method instead to parse the string value.

    • If ch is one of the characters NUM_0 to NUM_9, MINUS, or PLUS, it means that the item is a numeric value. The method follows the same steps as described for the object case, but calls the parseNumber method instead to parse the numeric value. After parsing the number, it checks if the current character in the source is either the ARRAY_END_TOKEN or the ARRAY_SEP. If it's the ARRAY_END_TOKEN, it means that the array ends after this item, so the method returns true to indicate that the parsing of the array is complete. If it's the ARRAY_SEP, it means that more items are present in the array, so the method continues parsing the next item by returning false.

    • If ch is equal to ARRAY_END_TOKEN, it means that the array ends after this item. The method checks if the startChar is the ARRAY_SEP character, which indicates a trailing comma in the array. If it's a trailing comma, the method throws an UnexpectedCharacterException with a message indicating the presence of a trailing comma. Otherwise, it simply moves to the next character in the source and returns true to indicate that the parsing of the array is complete.

    • If none of the above cases match, it means that the character ch is not a valid character for an item in the JSON array. The method throws an UnexpectedCharacterException with a message indicating that an unexpected character was encountered while parsing the array item.

  4. Finally, if none of the above cases match and no exception is thrown, the method returns false to indicate that the parsing of the array is not yet complete and there are more items to be parsed.

This is a general overview of the parseArrayItem method and its behavior based on the provided code snippet.

The parseArrayItem method in the JsonEventFastParser class is responsible for parsing an item within a JSON array.

It takes in a CharSource object, which represents the source of characters to be parsed, and a TokenEventListener object, which handles the events generated during parsing.

The method starts by getting the current character from the CharSource and then reads the next character after skipping any white space.

It then checks the value of the character and performs different actions based on its value. If the character indicates the start of an object, it calls the parseObject method and generates the appropriate start and end tokens for the array item. Similarly, if the character indicates the start of an array, boolean value (true/false), null value, string, or number, it calls the respective parsing methods and generates the corresponding tokens.

If the character is a digit or special character that indicates the start of a number, the method parses the number and checks if the current character is either the end of the array or a comma separator. If it is the end of the array, the method returns true to indicate that the item has been parsed successfully.

If the character is the end token of an array, the method returns true if and only if the start character of the array item is a comma separator. This is to check if there is a trailing comma after the last item in the array, which is not allowed in JSON.

If none of the above conditions are met, the method throws an exception indicating that an unexpected character was encountered.

Finally, the method returns false to indicate that the item has not been fully parsed yet.

This method is used internally by the parser to parse individual items within a JSON array.

private void parseNumber(final CharSource source, final TokenEventListener event)

private void parseNumber(final CharSource source, final TokenEventListener event) {
    final int startIndex = source.getIndex();
    final NumberParseResult numberParse = source.findEndOfNumber();
    final int tokenType = numberParse.wasFloat() ? TokenTypes.FLOAT_TOKEN : TokenTypes.INT_TOKEN;
    event.start(tokenType, startIndex, source);
    event.end(tokenType, numberParse.endIndex(), source);
}

The parseNumber method, which is defined in the class io.nats.jparse.parser.event.JsonEventFastParser, is responsible for parsing numbers from a given character source and notifying a token event listener about the parsed number.

Here is a step-by-step description of what the parseNumber method does:

  1. It takes two parameters: source, which is the character source containing the JSON string, and event, which is the token event listener that will be notified about the parsed number.

  2. It retrieves the current index of the character source using the getIndex() method and assigns it to the startIndex variable. This will be the starting index of the parsed number.

  3. It calls the findEndOfNumber() method on the source object to find the end index of the number. This method scans the character source and determines the end index of the number, taking into account the decimal point and scientific notation if present. The result of this operation is stored in the numberParse variable, which is of type NumberParseResult.

  4. It determines the token type based on the result of the wasFloat() method called on numberParse. If the parsed number is a float, the token type is set to TokenTypes.FLOAT_TOKEN. Otherwise, it is set to TokenTypes.INT_TOKEN.

  5. It notifies the token event listener that a number token is starting by calling the start() method on event. This method takes three parameters: the token type, the startIndex, and the source object. This allows the event listener to handle the start of a number token.

  6. It notifies the token event listener that a number token has ended by calling the end() method on event. This method also takes three parameters: the token type, the end index obtained from numberParse, and the source object. This allows the event listener to handle the end of a number token.

Overall, the parseNumber method scans the character source to find the end index of a number, determines its type (float or integer), and notifies the token event listener about the start and end of the number token.

The parseNumber method in the JsonEventFastParser class is responsible for parsing a number from a given CharSource and notifying the TokenEventListener about the parsed number.

Here is a breakdown of what the method does:

  1. It saves the starting index of the current parsing position in the source using source.getIndex().
  2. Then, it uses the findEndOfNumber() method of the source to parse the number and stores the result in numberParse.
  3. Next, it determines the tokenType based on whether the parsed number was a float or an integer, using the wasFloat() method of numberParse.
  4. It notifies the TokenEventListener that a new token is starting by calling its start() method with the tokenType, the startIndex, and the source.
  5. Finally, it notifies the TokenEventListener that the token has ended by calling its end() method with the tokenType, the endIndex() obtained from numberParse, and the source.

In summary, the parseNumber method parses a number from the source and lets the TokenEventListener know about the token's type, starting and ending positions.

sequence diagram

private boolean parseKey(final CharSource source, final TokenEventListener event)

private boolean parseKey(final CharSource source, final TokenEventListener event) {
    int ch = source.nextSkipWhiteSpace();
    event.start(TokenTypes.ATTRIBUTE_KEY_TOKEN, source.getIndex(), source);
    boolean found = false;
    switch(ch) {
        case STRING_START_TOKEN:
            final int strStartIndex = source.getIndex();
            event.start(TokenTypes.STRING_TOKEN, strStartIndex + 1, source);
            final int strEndIndex;
            if (objectsKeysCanBeEncoded) {
                strEndIndex = source.findEndOfEncodedString();
            } else {
                strEndIndex = source.findEndString();
            }
            found = true;
            event.end(TokenTypes.STRING_TOKEN, strEndIndex, source);
            break;
        case OBJECT_END_TOKEN:
            return true;
        default:
            throw new UnexpectedCharacterException("Parsing key", "Unexpected character found", source);
    }
    boolean done = source.findObjectEndOrAttributeSep();
    if (!done && found) {
        event.end(TokenTypes.ATTRIBUTE_KEY_TOKEN, source.getIndex(), source);
    } else if (found && done) {
        throw new UnexpectedCharacterException("Parsing key", "Not found", source);
    }
    return done;
}

The parseKey method is defined in the JsonEventFastParser class of the io.nats.jparse.parser.event package.

Here is a step-by-step description of what the parseKey method does based on its body:

  1. It takes two parameters: source of type CharSource and event of type TokenEventListener.
  2. It retrieves the next character from the source while skipping any whitespace.
  3. It notifies the event that a new ATTRIBUTE_KEY_TOKEN is being started, providing the index and the source.
  4. It uses a switch statement to handle different cases for the retrieved character:
    • If the character is STRING_START_TOKEN, it means that a new string token is starting.
      • It notifies the event that a new STRING_TOKEN is being started, providing the index plus one (to exclude the STRING_START_TOKEN) and the source.
      • It determines the end index of the string token:
        • If objectsKeysCanBeEncoded is true, it uses the findEndOfEncodedString() method of the source to locate the end of the encoded string.
        • If objectsKeysCanBeEncoded is false, it uses the findEndString() method of the source to locate the end of the string.
      • It sets found to true to indicate that a string token has been found.
      • It notifies the event that the STRING_TOKEN is ending, providing the end index and the source.
    • If the character is OBJECT_END_TOKEN, it means that the end of the object is reached.
      • It returns true to indicate that the parsing of the key is done.
    • If none of the above cases match, it throws an UnexpectedCharacterException with a message indicating that an unexpected character is found in the key parsing, along with the source.
  5. It attempts to find the end of the object or the attribute separator in the source, and assigns the result to the done variable.
  6. If done is false and found is true, it notifies the event that the ATTRIBUTE_KEY_TOKEN is ending, providing the current index and the source.
  7. If found is true and done is true, it throws an UnexpectedCharacterException with a message indicating that the end of the key is not found, along with the source.
  8. It returns the value of done, indicating whether the parsing of the key is done or not.

The method parseKey is a part of the JsonEventFastParser class in the io.nats.jparse.parser.event package.

This method is responsible for parsing the key of a JSON attribute. It takes a CharSource object and a TokenEventListener object as parameters.

The method begins by skipping any whitespace characters in the source and then starts the attribute key token event. It then checks the next character in the source.

If the next character is a string start token, the method starts a string token event, determines the end index of the string, and sets the found flag to true. The method then ends the string token event.

If the next character is an object end token, the method returns true.

If none of the above conditions are met, the method throws an UnexpectedCharacterException with a relevant message.

Finally, the method checks if the parsing is done by finding the end of the object or the attribute separator in the source. If parsing is not yet done and the found flag is true, the method ends the attribute key token event. If parsing is done and the found flag is true, the method throws an UnexpectedCharacterException with a relevant message.

The method returns the value of the done variable, indicating whether the parsing of the key is completed or not.

private boolean parseValue(final CharSource source, final TokenEventListener event)

private boolean parseValue(final CharSource source, final TokenEventListener event) {
    int ch = source.nextSkipWhiteSpace();
    event.start(TokenTypes.ATTRIBUTE_VALUE_TOKEN, source.getIndex(), source);
    switch(ch) {
        case OBJECT_START_TOKEN:
            parseObject(source, event);
            break;
        case ARRAY_START_TOKEN:
            parseArray(source, event);
            break;
        case TRUE_BOOLEAN_START:
            parseTrue(source, event);
            break;
        case FALSE_BOOLEAN_START:
            parseFalse(source, event);
            break;
        case NULL_START:
            parseNull(source, event);
            break;
        case STRING_START_TOKEN:
            parseString(source, event);
            break;
        case NUM_0:
        case NUM_1:
        case NUM_2:
        case NUM_3:
        case NUM_4:
        case NUM_5:
        case NUM_6:
        case NUM_7:
        case NUM_8:
        case NUM_9:
        case MINUS:
        case PLUS:
            parseNumber(source, event);
            break;
        default:
            throw new UnexpectedCharacterException("Parsing Value", "Unexpected character", source, ch);
    }
    source.skipWhiteSpace();
    switch(source.getCurrentChar()) {
        case OBJECT_END_TOKEN:
            event.end(TokenTypes.ATTRIBUTE_VALUE_TOKEN, source.getIndex(), source);
            return true;
        case OBJECT_ATTRIBUTE_SEP:
            event.end(TokenTypes.ATTRIBUTE_VALUE_TOKEN, source.getIndex(), source);
            return false;
        default:
            throw new UnexpectedCharacterException("Parsing Value", "Unexpected character", source, source.getCurrentChar());
    }
}

The parseValue method in the JsonEventFastParser class is responsible for parsing a JSON value from a given source and generating corresponding events through a TokenEventListener.

Here is a step-by-step description of what the parseValue method does based on its body:

  1. The method starts by skipping any white space characters in the source and then notifies the event listener that a new attribute value token is about to be processed.

  2. It reads the next character from the source and performs a switch case based on its value:

    • If the character is the start of an object ({), it calls the parseObject method to parse the object.
    • If the character is the start of an array ([), it calls the parseArray method to parse the array.
    • If the character is the start of a boolean true value (true), it calls the parseTrue method to parse the true value.
    • If the character is the start of a boolean false value (false), it calls the parseFalse method to parse the false value.
    • If the character is the start of a null value (null), it calls the parseNull method to parse the null value.
    • If the character is the start of a string ("), it calls the parseString method to parse the string.
    • If the character is a digit or a minus/plus sign (0-9, -, +), it calls the parseNumber method to parse a number.
    • If none of the above cases match, it throws an UnexpectedCharacterException with an error message.
  3. After parsing the value, the method skips any remaining white space characters in the source.

  4. It then performs another switch case based on the current character in the source:

    • If the character is the end of an object (}), it notifies the event listener that the attribute value token has ended and returns true.
    • If the character is the separator between object attributes (:), it notifies the event listener that the attribute value token has ended and returns false.
    • If none of the above cases match, it throws an UnexpectedCharacterException with an error message.

This method is responsible for handling the main types of JSON values (objects, arrays, booleans, null, strings, and numbers) and generating appropriate events for each value type through the event listener.

The parseValue method in the JsonEventFastParser class is responsible for parsing a JSON value from a given CharSource and notifying a TokenEventListener with the parsed value.

First, it reads the next character from the source and skips any whitespace. It then notifies the event listener that it is starting to parse an attribute value token.

Based on the type of the character read, it performs the following actions:

  • If the character is the start of an object token, it invokes the parseObject method.
  • If the character is the start of an array token, it invokes the parseArray method.
  • If the character is the start of a true boolean token, it invokes the parseTrue method.
  • If the character is the start of a false boolean token, it invokes the parseFalse method.
  • If the character is the start of a null token, it invokes the parseNull method.
  • If the character is the start of a string token, it invokes the parseString method.
  • If the character is a digit or a symbol related to numbers, it invokes the parseNumber method.
  • If none of the above cases match, it throws an exception for encountering an unexpected character.

After parsing the value and skipping any whitespace, it checks the current character of the source. If it is the end of an object token, it notifies the event listener and returns true. If it is a comma separating object attributes, it notifies the event listener and returns false. If none of these cases match, it throws an exception for encountering an unexpected character.

Overall, the parseValue method efficiently parses and validates a JSON value, handling various types such as objects, arrays, booleans, null, numbers, and strings.

sequence diagram

private void parseObject(final CharSource source, final TokenEventListener event)

private void parseObject(final CharSource source, final TokenEventListener event) {
    event.start(TokenTypes.OBJECT_TOKEN, source.getIndex(), source);
    boolean done = false;
    while (!done) {
        done = parseKey(source, event);
        if (!done)
            done = parseValue(source, event);
    }
    if (source.getCurrentChar() != OBJECT_END_TOKEN) {
        throw new UnexpectedCharacterException("Parsing Object", "Unexpected character", source, source.getCurrentCharSafe());
    }
    source.next();
    event.end(TokenTypes.OBJECT_TOKEN, source.getIndex(), source);
}

The parseObject method in the JsonEventFastParser class is used to parse a JSON object. Here's a step-by-step description of how the method works:

  1. It starts by invoking the start method of the TokenEventListener with the token type OBJECT_TOKEN to indicate the beginning of parsing an object. It also provides the index and the character source.

  2. It initializes a boolean variable done to false, which will be used to determine when parsing is complete.

  3. It enters a while loop, which continues until done is true. This loop iteratively parses the key-value pairs within the JSON object.

  4. Inside the loop, it calls the parseKey method to parse the key of the key-value pair. The parseKey method is expected to return a boolean value indicating whether the key parsing is complete.

  5. If the parseKey method returns false, it means the key parsing is not yet complete, so it calls the parseValue method to parse the value of the key-value pair.

  6. After parsing the key and value, it checks if the current character is the end of the object token (OBJECT_END_TOKEN). If it's not, it throws an UnexpectedCharacterException, indicating that an unexpected character was found when parsing the JSON object.

  7. If the current character is the end of the object token, it moves to the next character in the source by invoking the next method.

  8. Finally, it invokes the end method of the TokenEventListener with the token type OBJECT_TOKEN to indicate the end of parsing an object. It also provides the index and the character source.

This method essentially handles the parsing of a JSON object by calling helper methods to parse the key-value pairs and verifying the end of the object token.

The parseObject method in the class io.nats.jparse.parser.event.JsonEventFastParser is responsible for parsing a JSON object from a given input source.

The method starts by notifying the event listener that an object token is being parsed. It then enters a loop, where it alternates between parsing a key and parsing a value until the end of the object is reached.

After the loop, the method checks if the last character of the input source is the expected object end token. If it's not, an UnexpectedCharacterException is thrown.

Finally, the method notifies the event listener that the parsing of the object is complete.

sequence diagram

JsonEventAbstractParser

The JsonEventAbstractParser class provides shared code for event parsers. It is an abstract class that implements the JsonEventParser and JsonParser interfaces. This class serves as a base for implementing event-based JSON parsers.

@Override

public List scan(final CharSource source)

@Override
public List<Token> scan(final CharSource source) {
    tokenList = new TokenList();
    this.parseWithEvents(source, base);
    return tokenList;
}

Method: scan()

This method is defined in the io.nats.jparse.parser.event.JsonEventAbstractParser class.

Parameters:

  • source: The CharSource object representing the input source to be scanned.

Return Type:

  • List<Token>: The list of tokens generated by the scan process.

Steps:

  1. Create a new TokenList object to store the generated tokens.
  2. Call the parseWithEvents method passing the source and base parameters, along with the current instance of the class. This method is responsible for parsing the input source and generating events based on the JSON syntax.
  3. Return the populated tokenList which now contains the tokens generated during the parsing process.

The scan method is an overridden method in the JsonEventAbstractParser class. It accepts a CharSource object as a parameter and returns a list of Token objects.

Within the method, a new instance of TokenList is created. The parseWithEvents method is called with the provided source and base parameters. This method is responsible for parsing the source and generating appropriate events based on the JSON structure.

Once the parsing is completed, the tokenList, which contains the generated Token objects, is returned. The Token objects represent the different elements found in the JSON structure, such as keys, values, arrays, and objects.

sequence diagram

JsonEventStrictParser

The JsonEventStrictParser class is a strict JSON parser that extends the JsonEventAbstractParser class. It provides functionality for parsing JSON data in a strict manner.

@Override

public void parseWithEvents(CharSource source, final TokenEventListener event)

@Override
public void parseWithEvents(CharSource source, final TokenEventListener event) {
    int ch = source.nextSkipWhiteSpace();
    switch(ch) {
        case ParseConstants.OBJECT_START_TOKEN:
            parseObject(source, event);
            break;
        case ParseConstants.ARRAY_START_TOKEN:
            parseArray(source, event);
            break;
        case ParseConstants.TRUE_BOOLEAN_START:
            parseTrue(source, event);
            break;
        case ParseConstants.FALSE_BOOLEAN_START:
            parseFalse(source, event);
            break;
        case ParseConstants.NULL_START:
            parseNull(source, event);
            break;
        case ParseConstants.STRING_START_TOKEN:
            parseString(source, event);
            break;
        case ParseConstants.NUM_0:
        case ParseConstants.NUM_1:
        case ParseConstants.NUM_2:
        case ParseConstants.NUM_3:
        case ParseConstants.NUM_4:
        case ParseConstants.NUM_5:
        case ParseConstants.NUM_6:
        case ParseConstants.NUM_7:
        case ParseConstants.NUM_8:
        case ParseConstants.NUM_9:
        case ParseConstants.MINUS:
        case ParseConstants.PLUS:
            parseNumber(source, event);
            break;
        default:
            throw new UnexpectedCharacterException("Scanning JSON", "Unexpected character", source, (char) ch);
    }
    source.checkForJunk();
}

The parseWithEvents method in the JsonEventStrictParser class is responsible for parsing a JSON document step by step and triggering events based on the encountered tokens.

Here is a step-by-step description of what this method does:

  1. It takes two parameters: source, which is the CharSource (a character source providing the JSON document), and event, which is the TokenEventListener (to handle events).

  2. It reads the next character from the source and skips any leading whitespace.

  3. It uses a switch statement to determine the type of token based on the read character:

    • If the token is an object start token ({), it calls the parseObject method, passing the source and event as parameters.

    • If the token is an array start token ([), it calls the parseArray method, passing the source and event as parameters.

    • If the token is a true boolean start token, it calls the parseTrue method, passing the source and event as parameters.

    • If the token is a false boolean start token, it calls the parseFalse method, passing the source and event as parameters.

    • If the token is a null start token, it calls the parseNull method, passing the source and event as parameters.

    • If the token is a string start token ("), it calls the parseString method, passing the source and event as parameters.

    • If the token is a numeric digit or a minus/plus sign, it calls the parseNumber method, passing the source and event as parameters.

    • If the token does not match any of the above cases, it throws an UnexpectedCharacterException with a descriptive error message.

  4. After parsing the token, it checks for any additional junk characters in the source and throws an exception if any leftovers are found.

In summary, the parseWithEvents method reads each character from the input JSON document, identifies its type, and calls the appropriate parsing method. It also ensures that there are no unexpected characters or junk at the end of the document.

The parseWithEvents method in the JsonEventStrictParser class is used to parse a JSON input using events.

Here's what the method does:

  1. It reads the next character from the input source and skips any whitespace.
  2. It then checks the type of the character and performs the appropriate action:
    • If the character represents the start of an object ('{'), it calls the parseObject method.
    • If the character represents the start of an array ('['), it calls the parseArray method.
    • If the character represents the start of a true boolean value ('t'), it calls the parseTrue method.
    • If the character represents the start of a false boolean value ('f'), it calls the parseFalse method.
    • If the character represents the start of a null value ('n'), it calls the parseNull method.
    • If the character represents the start of a string ('"'), it calls the parseString method.
    • If the character represents a number (0-9, '-', '+'), or a decimal point, it calls the parseNumber method.
    • If none of the above cases match, it throws an UnexpectedCharacterException.
  3. After parsing the value, it checks for any additional junk characters in the input source using the checkForJunk method.

Overall, the parseWithEvents method allows for parsing a JSON input by handling different JSON types and invoking appropriate event callbacks for each type.

sequence diagram

private void parseArray(final CharSource source, final TokenEventListener event)

private void parseArray(final CharSource source, final TokenEventListener event) {
    levelCheck(source);
    event.start(TokenTypes.ARRAY_TOKEN, source.getIndex(), source);
    boolean done = false;
    while (!done) {
        done = parseArrayItem(source, event);
        if (!done) {
            done = source.findCommaOrEndForArray();
        }
    }
    event.end(TokenTypes.ARRAY_TOKEN, source.getIndex(), source);
}

The parseArray method is a private method defined in the io.nats.jparse.parser.event.JsonEventStrictParser class. It takes two parameters: source of type CharSource and event of type TokenEventListener.

Here is a step-by-step description of what the parseArray method does based on its body:

  1. It starts by calling a method called levelCheck passing the source parameter. This method performs some checks related to the level of the parsing.
  2. It then calls the start method on the event parameter, passing TokenTypes.ARRAY_TOKEN, source.getIndex() (current index in the source), and source itself. This indicates the start of an array token to the TokenEventListener.
  3. It initializes a boolean variable called done as false.
  4. It enters a while loop that continues until done is true.
  5. Inside the loop, it calls a method called parseArrayItem passing the source and event parameters. This method is responsible for parsing each item within the array.
  6. After the parseArrayItem method returns, it checks if the done variable is still false.
    • If done is still false, it calls the findCommaOrEndForArray method on the source to find the next comma or end of the array.
    • If done is true, it exits the while loop.
  7. After the while loop, it calls the end method on the event parameter, passing TokenTypes.ARRAY_TOKEN, source.getIndex() (current index in the source), and source itself. This indicates the end of the array token to the TokenEventListener.

In summary, the parseArray method is responsible for parsing an array from the source using the parseArrayItem method and notifying the TokenEventListener about the start and end of the array token.

The parseArray method is a private method defined in the JsonEventStrictParser class. It is responsible for parsing an array from a given CharSource while notifying an TokenEventListener about the encountered events.

Here is a breakdown of what the method does:

  1. It performs a level check on the provided CharSource.
  2. It notifies the TokenEventListener that the start of an array token has been encountered.
  3. A loop is initiated until the parsing of the array is complete.
  4. Inside the loop, it calls the parseArrayItem method to parse each item in the array. The TokenEventListener is notified about the parsed item.
  5. After parsing an item, it checks if the parsing is complete by calling the findCommaOrEndForArray method on the CharSource. If a comma is found, the loop continues to parse the next item. If the end of the array is encountered, the loop is terminated.
  6. Finally, it notifies the TokenEventListener that the end of the array token has been encountered, providing the index of the CharSource.

In summary, the parseArray method is responsible for parsing an array from a CharSource and notifying the TokenEventListener about the start and end of the array token, as well as each individual array item.

sequence diagram

private boolean parseArrayItem(CharSource source, final TokenEventListener event)

private boolean parseArrayItem(CharSource source, final TokenEventListener event) {
    char startChar = source.getCurrentChar();
    int ch = source.nextSkipWhiteSpace();
    switch(ch) {
        case ParseConstants.OBJECT_START_TOKEN:
            event.start(TokenTypes.ARRAY_ITEM_TOKEN, source.getIndex(), source);
            parseObject(source, event);
            event.end(TokenTypes.ARRAY_ITEM_TOKEN, source.getIndex(), source);
            break;
        case ParseConstants.ARRAY_START_TOKEN:
            event.start(TokenTypes.ARRAY_ITEM_TOKEN, source.getIndex(), source);
            parseArray(source, event);
            event.end(TokenTypes.ARRAY_ITEM_TOKEN, source.getIndex(), source);
            break;
        case ParseConstants.TRUE_BOOLEAN_START:
            event.start(TokenTypes.ARRAY_ITEM_TOKEN, source.getIndex(), source);
            parseTrue(source, event);
            event.end(TokenTypes.ARRAY_ITEM_TOKEN, source.getIndex(), source);
            break;
        case ParseConstants.FALSE_BOOLEAN_START:
            event.start(TokenTypes.ARRAY_ITEM_TOKEN, source.getIndex(), source);
            parseFalse(source, event);
            event.end(TokenTypes.ARRAY_ITEM_TOKEN, source.getIndex(), source);
            break;
        case ParseConstants.NULL_START:
            event.start(TokenTypes.ARRAY_ITEM_TOKEN, source.getIndex(), source);
            parseNull(source, event);
            event.end(TokenTypes.ARRAY_ITEM_TOKEN, source.getIndex(), source);
            break;
        case ParseConstants.STRING_START_TOKEN:
            event.start(TokenTypes.ARRAY_ITEM_TOKEN, source.getIndex(), source);
            parseString(source, event);
            event.end(TokenTypes.ARRAY_ITEM_TOKEN, source.getIndex(), source);
            break;
        case ParseConstants.NUM_0:
        case ParseConstants.NUM_1:
        case ParseConstants.NUM_2:
        case ParseConstants.NUM_3:
        case ParseConstants.NUM_4:
        case ParseConstants.NUM_5:
        case ParseConstants.NUM_6:
        case ParseConstants.NUM_7:
        case ParseConstants.NUM_8:
        case ParseConstants.NUM_9:
        case ParseConstants.MINUS:
        case ParseConstants.PLUS:
            event.start(TokenTypes.ARRAY_ITEM_TOKEN, source.getIndex(), source);
            parseNumber(source, event);
            event.end(TokenTypes.ARRAY_ITEM_TOKEN, source.getIndex(), source);
            if (source.getCurrentChar() == ParseConstants.ARRAY_END_TOKEN || source.getCurrentChar() == ParseConstants.ARRAY_SEP) {
                if (source.getCurrentChar() == ParseConstants.ARRAY_END_TOKEN) {
                    source.next();
                    return true;
                }
            }
            break;
        case ParseConstants.ARRAY_END_TOKEN:
            if (startChar == ParseConstants.ARRAY_SEP) {
                throw new UnexpectedCharacterException("Parsing Array Item", "Trailing comma", source, (char) ch);
            }
            source.next();
            return true;
        default:
            throw new UnexpectedCharacterException("Parsing Array Item", "Unexpected character", source, (char) ch);
    }
    return false;
}

The parseArrayItem method in the JsonEventStrictParser class is responsible for parsing individual items in a JSON array. Here is a step-by-step description of what the method does:

  1. The method takes two parameters: source, which is the input source containing the JSON array, and event, which is the event listener that will be notified of parsing events.

  2. It starts by getting the current character from the source and storing it in the startChar variable.

  3. The method then calls the nextSkipWhitespace method on the input source to skip any whitespace characters and get the next character in the source, which is stored in the ch variable.

  4. The method enters a switch statement based on the value of ch.

  5. If the value of ch is equal to ParseConstants.OBJECT_START_TOKEN (which represents the start of a JSON object), it notifies the event listener that an array item has started, and then calls the parseObject method to parse the JSON object. After the object is parsed, it notifies the event listener that the array item has ended.

  6. If the value of ch is equal to ParseConstants.ARRAY_START_TOKEN (which represents the start of another JSON array), it follows a similar process as in step 5, but calls the parseArray method instead to parse the array.

  7. If the value of ch is equal to ParseConstants.TRUE_BOOLEAN_START or ParseConstants.FALSE_BOOLEAN_START (which represent the start of a boolean value), it again follows a similar process as in step 5, but calls the parseTrue or parseFalse method respectively to parse the boolean value.

  8. If the value of ch is equal to ParseConstants.NULL_START (which represents the start of a null value), it follows a similar process as in step 5, but calls the parseNull method to parse the null value.

  9. If the value of ch is equal to ParseConstants.STRING_START_TOKEN (which represents the start of a string value), it follows a similar process as in step 5, but calls the parseString method to parse the string value.

  10. If the value of ch is one of ParseConstants.NUM_0, ParseConstants.NUM_1, ..., ParseConstants.NUM_9, ParseConstants.MINUS, or ParseConstants.PLUS (which represent the start of a number), it again follows a similar process as in step 5, but calls the parseNumber method to parse the number value. It then checks if the current character in the source is either the end of the JSON array or a comma separator. If it is, it checks if the current character is the end of the JSON array, and if so, it returns true (indicating that the parsing of the array is complete).

  11. If the value of ch is equal to ParseConstants.ARRAY_END_TOKEN, it checks if the startChar variable is equal to ParseConstants.ARRAY_SEP (which represents a trailing comma in the array). If it is, it throws an exception indicating that a trailing comma is not allowed. Otherwise, it moves to the next character in the source and returns true (indicating that the parsing of the array is complete).

  12. If none of the above cases match, it throws an exception indicating that an unexpected character was encountered while parsing the array item.

  13. Finally, the method returns false to indicate that the parsing of the array item is not complete.

The method parseArrayItem is used to parse an item within a JSON array. It takes a CharSource and a TokenEventListener as parameters.

First, it retrieves the current character from the CharSource and skips any whitespace characters. Then, it enters a switch statement based on the retrieved character.

  • If the character indicates the start of an object ({), it invokes the parseObject method to further parse the object, and notifies the TokenEventListener of the start and end of the array item.
  • If the character indicates the start of another array ([), it invokes the parseArray method to further parse the nested array, and notifies the TokenEventListener of the start and end of the array item.
  • If the character indicates the start of a boolean true, it invokes the parseTrue method to parse the boolean value, and notifies the TokenEventListener of the start and end of the array item.
  • If the character indicates the start of a boolean false, it invokes the parseFalse method to parse the boolean value, and notifies the TokenEventListener of the start and end of the array item.
  • If the character indicates the start of a null value, it invokes the parseNull method to parse the value, and notifies the TokenEventListener of the start and end of the array item.
  • If the character indicates the start of a string ("), it invokes the parseString method to parse the string value, and notifies the TokenEventListener of the start and end of the array item.
  • If the character indicates the start of a number (0-9, minus sign, plus sign), it invokes the parseNumber method to parse the number value, and notifies the TokenEventListener of the start and end of the array item. It then checks if the current character is either the end of the array or a separator, and if so, it returns true to indicate that the parsing of the array item is complete.
  • If the character indicates the end of the array (]), it checks if the previous character was a separator. If so, it throws an exception for a trailing comma. Otherwise, it advances to the next character and returns true to indicate the end of the parsing.

If none of the above cases match, it throws an exception for an unexpected character in the array item.

Finally, if the parsing is not complete, it returns false.

private void parseNumber(final CharSource source, final TokenEventListener event)

private void parseNumber(final CharSource source, final TokenEventListener event) {
    final int startIndex = source.getIndex();
    final NumberParseResult numberParse = source.findEndOfNumber();
    final int tokenType = numberParse.wasFloat() ? TokenTypes.FLOAT_TOKEN : TokenTypes.INT_TOKEN;
    event.start(tokenType, startIndex, source);
    event.end(tokenType, numberParse.endIndex(), source);
}

The parseNumber method in the JsonEventStrictParser class is responsible for parsing a number from a given character source and notifying the event listener about the parsed token.

Here is a step-by-step description of what the parseNumber method does:

  1. Retrieve the current index in the character source using source.getIndex() and store it in startIndex variable.
  2. Utilize the findEndOfNumber method from the CharSource class to locate the end position of the number being parsed. This method returns a NumberParseResult object, which contains information about whether the number was parsed as a float or an integer.
  3. Determine the token type based on whether the number was parsed as a float or an integer. If it was a float, assign TokenTypes.FLOAT_TOKEN to the tokenType variable. Otherwise, assign TokenTypes.INT_TOKEN.
  4. Notify the event listener that parsing of the number is starting by invoking event.start() method and passing the tokenType, startIndex, and the original source as arguments.
  5. Notify the event listener that parsing of the number has ended by invoking event.end() method and passing the tokenType, the end index of the parsed number obtained from numberParse.endIndex(), and the original source as arguments.

Overall, the parseNumber method scans the character source for numbers, determines their types, and informs the event listener of the start and end positions of the parsed numbers using the appropriate token types.

The method parseNumber in class JsonEventStrictParser is used to parse a number from a CharSource object.

  • It first gets the starting index of the number from the CharSource using source.getIndex().
  • Then, it uses the findEndOfNumber method on the CharSource to determine the end of the number and obtain a NumberParseResult object.
  • Based on whether the number was a float or an integer, it assigns the appropriate token type TokenTypes.FLOAT_TOKEN or TokenTypes.INT_TOKEN.
  • It then calls the start and end methods on the TokenEventListener object event to notify the start and end of the number token, passing the token type, start index, end index, and the CharSource object.

sequence diagram

private boolean parseKey(final CharSource source, final TokenEventListener event)

private boolean parseKey(final CharSource source, final TokenEventListener event) {
    final char startChar = source.getCurrentChar();
    int ch = source.nextSkipWhiteSpace();
    event.start(TokenTypes.ATTRIBUTE_KEY_TOKEN, source.getIndex(), source);
    boolean found = false;
    switch(ch) {
        case ParseConstants.STRING_START_TOKEN:
            final int strStartIndex = source.getIndex();
            event.start(TokenTypes.STRING_TOKEN, strStartIndex + 1, source);
            final int strEndIndex;
            if (objectsKeysCanBeEncoded) {
                strEndIndex = source.findEndOfEncodedString();
            } else {
                strEndIndex = source.findEndString();
            }
            found = true;
            event.end(TokenTypes.STRING_TOKEN, strEndIndex, source);
            break;
        case ParseConstants.OBJECT_END_TOKEN:
            if (startChar == ParseConstants.OBJECT_ATTRIBUTE_SEP) {
                throw new UnexpectedCharacterException("Parsing key", "Unexpected character found", source);
            }
            return true;
        default:
            throw new UnexpectedCharacterException("Parsing key", "Unexpected character found", source);
    }
    boolean done = source.findObjectEndOrAttributeSep();
    if (!done && found) {
        event.end(TokenTypes.ATTRIBUTE_KEY_TOKEN, source.getIndex(), source);
    } else if (found && done) {
        throw new UnexpectedCharacterException("Parsing key", "Not found", source);
    }
    return done;
}

Method: parseKey

This method is defined in the JsonEventStrictParser class within the io.nats.jparse.parser.event package. It takes two parameters: a CharSource object named source and a TokenEventListener object named event. The method returns a boolean value.

Step 1: Store the starting character of the source

  • Get the starting character from the source object and store it in a local variable called startChar.

Step 2: Move to the next non-whitespace character in the source

  • Call the nextSkipWhiteSpace() method on the source object to move to the next non-whitespace character.
  • Store the resulting character in a local variable named ch.

Step 3: Start the ATTRIBUTE_KEY_TOKEN event

  • Call the start() method on the event object, passing TokenTypes.ATTRIBUTE_KEY_TOKEN as the token type, the current index of the source, and the source object itself.

Step 4: Check the type of the character

  • Use a switch statement to check the type of the character ch.

Step 5: Handle STRING_START_TOKEN case

  • If ch is equal to ParseConstants.STRING_START_TOKEN:
    1. Store the current index of the source object in a local variable called strStartIndex.
    2. Call the start() method on the event object, passing TokenTypes.STRING_TOKEN as the token type, (strStartIndex + 1) as the start index, and the source object itself.
    3. Determine the end index of the string based on the value of objectsKeysCanBeEncoded.
    4. If objectsKeysCanBeEncoded is true, call the findEndOfEncodedString() method on the source object to find the end index of the string.
    5. If objectsKeysCanBeEncoded is false, call the findEndString() method on the source object to find the end index of the string.
    6. Set the found variable to true.
    7. Call the end() method on the event object, passing TokenTypes.STRING_TOKEN as the token type, the end index of the string, and the source object itself.

Step 6: Handle OBJECT_END_TOKEN case

  • If ch is equal to ParseConstants.OBJECT_END_TOKEN:
    • Check if the startChar is equal to ParseConstants.OBJECT_ATTRIBUTE_SEP.
    • If true, throw an UnexpectedCharacterException with the message "Unexpected character found" and the source object.
    • Return true.

Step 7: Handle default case

  • If none of the above cases match, throw an UnexpectedCharacterException with the message "Unexpected character found" and the source object.

Step 8: Find the end of the object or attribute separator

  • Call the findObjectEndOrAttributeSep() method on the source object and store the result in a boolean variable named done.

Step 9: Check if the object is not done and a key is found

  • If done is false and found is true, call the end() method on the event object, passing TokenTypes.ATTRIBUTE_KEY_TOKEN as the token type, the current index of the source, and the source object itself.

Step 10: Check if a key is found but the object is done

  • If found is true and done is true, throw an UnexpectedCharacterException with the message "Not found" and the source object.

Step 11: Return the value of the done variable

  • This method returns the value of the done variable, indicating whether the parsing is done or not.

The parseKey method in the JsonEventStrictParser class is used to parse a key from a JSON input using a strict parsing approach.

Here's a step-by-step breakdown of how the method works:

  1. It takes a CharSource object, which represents the source of characters to be parsed, and a TokenEventListener object, which listens to the events generated during parsing.

  2. The method starts by capturing the current character of the source and reads the next character, skipping whitespace.

  3. It notifies the event listener that it is starting to parse an attribute key token.

  4. It evaluates the type of character read:

    • If the character is a string start token ("), it signifies the start of a string. The method then captures the starting index of the string and notifies the event listener that it is starting to parse a string token. It then identifies the end of the string, considering whether object keys can be encoded or not, and notifies the event listener that it has ended the string token.

    • If the character is an object end token (}), it checks if the start character of the key is the object attribute separator (:). If it is not, it throws an UnexpectedCharacterException indicating that an unexpected character was found while parsing the key. If it is, the method returns true, indicating that the parsing of the key is complete.

    • If none of the above conditions are met, it throws an UnexpectedCharacterException indicating that an unexpected character was found while parsing the key.

  5. If the parsing is not yet complete and a valid key was found, the method attempts to find either the end of the object or the attribute separator.

  6. If the parsing is not yet complete, but a valid key was found, the method notifies the event listener that it has ended the attribute key token.

  7. If the parsing is complete but a valid key was found, it throws an UnexpectedCharacterException indicating that the key was not found.

  8. Finally, the method returns whether the parsing is complete or not.

This method is useful for parsing individual keys from a JSON input and generating events for further processing.

private boolean parseValue(final CharSource source, final TokenEventListener event)

private boolean parseValue(final CharSource source, final TokenEventListener event) {
    int ch = source.nextSkipWhiteSpace();
    event.start(TokenTypes.ATTRIBUTE_VALUE_TOKEN, source.getIndex(), source);
    switch(ch) {
        case ParseConstants.OBJECT_START_TOKEN:
            parseObject(source, event);
            break;
        case ParseConstants.ARRAY_START_TOKEN:
            parseArray(source, event);
            break;
        case ParseConstants.TRUE_BOOLEAN_START:
            parseTrue(source, event);
            break;
        case ParseConstants.FALSE_BOOLEAN_START:
            parseFalse(source, event);
            break;
        case ParseConstants.NULL_START:
            parseNull(source, event);
            break;
        case ParseConstants.STRING_START_TOKEN:
            parseString(source, event);
            break;
        case ParseConstants.NUM_0:
        case ParseConstants.NUM_1:
        case ParseConstants.NUM_2:
        case ParseConstants.NUM_3:
        case ParseConstants.NUM_4:
        case ParseConstants.NUM_5:
        case ParseConstants.NUM_6:
        case ParseConstants.NUM_7:
        case ParseConstants.NUM_8:
        case ParseConstants.NUM_9:
        case ParseConstants.MINUS:
        case ParseConstants.PLUS:
            parseNumber(source, event);
            break;
        default:
            throw new UnexpectedCharacterException("Parsing Value", "Unexpected character", source, ch);
    }
    source.skipWhiteSpace();
    switch(source.getCurrentChar()) {
        case ParseConstants.OBJECT_END_TOKEN:
            event.end(TokenTypes.ATTRIBUTE_VALUE_TOKEN, source.getIndex(), source);
            return true;
        case ParseConstants.OBJECT_ATTRIBUTE_SEP:
            event.end(TokenTypes.ATTRIBUTE_VALUE_TOKEN, source.getIndex(), source);
            return false;
        default:
            throw new UnexpectedCharacterException("Parsing Value", "Unexpected character", source, source.getCurrentChar());
    }
}

The parseValue method in the JsonEventStrictParser class is used to parse a single JSON value from the input source.

Here is a step-by-step description of what the method is doing based on its body:

  1. The method starts by reading the next character from the input source and skipping any white space characters.

  2. It then notifies the token event listener that a new attribute value token has started.

  3. The method enters a switch case based on the value of the current character: a. If the current character is the start of an object ('{'), it calls the parseObject method to parse the object. b. If the current character is the start of an array ('['), it calls the parseArray method to parse the array. c. If the current character is the start of the true boolean value ('t'), it calls the parseTrue method to parse the boolean value true. d. If the current character is the start of the false boolean value ('f'), it calls the parseFalse method to parse the boolean value false. e. If the current character is the start of the null value ('n'), it calls the parseNull method to parse the null value. f. If the current character is the start of a string ('"'), it calls the parseString method to parse the string value. g. If the current character is a number or a minus or plus sign, it calls the parseNumber method to parse the numeric value. h. If none of the above cases match, it throws an UnexpectedCharacterException with an error message indicating that an unexpected character was encountered while parsing the value.

  4. After parsing the value, the method skips any white space characters in the input source.

  5. The method then enters another switch case based on the current character in the input source: a. If the current character is the end of an object ('}'), it notifies the token event listener that the attribute value token has ended and returns true. b. If the current character is the object attribute separator (','), it notifies the token event listener that the attribute value token has ended and returns false. c. If none of the above cases match, it throws an UnexpectedCharacterException with an error message indicating that an unexpected character was encountered while parsing the value.

In summary, the parseValue method in the JsonEventStrictParser class is responsible for parsing a single JSON value from the input source and notifying the token event listener about the start and end of the value token.

The parseValue method in the JsonEventStrictParser class is responsible for parsing a JSON value from a given source and notifying the token event listener about the parsed value.

The method starts by skipping any white space characters and then starts the parsing by identifying the type of the value based on the first character. It uses a switch statement to handle different types of values such as objects, arrays, booleans, null, strings, and numbers.

After parsing the value, it skips any remaining white space characters and checks the next character to determine the end of the value. If the next character is an object closing token (}), it notifies the token event listener and returns true. If the next character is an object attribute separator (:), it notifies the token event listener and returns false.

If the next character does not match any of the expected values, it throws an UnexpectedCharacterException with an appropriate error message.

Overall, the parseValue method is a critical part of the JSON parsing process and is responsible for parsing different types of JSON values and notifying the token event listener accordingly.

sequence diagram

private void parseObject(final CharSource source, final TokenEventListener event)

private void parseObject(final CharSource source, final TokenEventListener event) {
    levelCheck(source);
    event.start(TokenTypes.OBJECT_TOKEN, source.getIndex(), source);
    boolean done = false;
    while (!done) {
        done = parseKey(source, event);
        if (!done)
            done = parseValue(source, event);
    }
    if (source.getCurrentChar() != ParseConstants.OBJECT_END_TOKEN) {
        throw new UnexpectedCharacterException("Parsing Object", "Unexpected character", source, source.getCurrentCharSafe());
    }
    source.next();
    event.end(TokenTypes.OBJECT_TOKEN, source.getIndex(), source);
}

The method parseObject is defined in the class io.nats.jparse.parser.event.JsonEventStrictParser. It takes two parameters: source, which is of type CharSource, and event, which is of type TokenEventListener.

Here is a step-by-step description of what the method parseObject is doing:

  1. It performs a level check, which is not explained in the given code snippet.
  2. It starts the OBJECT_TOKEN event by calling event.start() method, passing the token type, the index of the source, and the source itself as parameters.
  3. It initializes a boolean variable called done to false.
  4. It enters a while loop that continues until done is true. This loop is used to parse the key-value pairs of the object.
  5. Inside the loop, it calls the parseKey method passing the source and event as arguments, and assigns the returned value to done.
  6. If parseKey did not parse a key successfully, it calls the parseValue method passing the source and event as arguments, and assigns the returned value to done.
  7. If source.getCurrentChar() is not the OBJECT_END_TOKEN (which indicates the end of the object), it throws an UnexpectedCharacterException. The exception message states that it was parsing an object and encountered an unexpected character. It also includes the source and the current character as additional information.
  8. It advances the source to the next character by calling source.next().
  9. It ends the OBJECT_TOKEN event by calling event.end() method, passing the token type, the index of the source, and the source itself as parameters.

The method parseObject is responsible for parsing an object in the JSON input, iterating over its key-value pairs, and notifying the TokenEventListener about the start and end of the object.

The parseObject method is used to parse a JSON object string. It takes in a source input and a token event listener as parameters.

The method starts by performing a level check to ensure the input is valid. It then calls the event.start method to notify the listener that a JSON object token has been encountered.

A while loop is used to efficiently parse the key-value pairs within the object. Inside the loop, it first calls parseKey method to parse the key and notifies the event listener. If the key parsing is not yet done, it then calls parseValue method to parse the corresponding value and notifies the listener. This process continues until all key-value pairs have been parsed.

After the object's closing token is encountered, the method checks if it matches the expected object end token. If it doesn't, an exception is thrown. Otherwise, it calls source.next() to move the cursor to the next character and calls event.end to notify the listener that the object parsing is complete.

In summary, the parseObject method reads a JSON object string, validates its structure, parses its key-value pairs, and notifies an event listener about the start and end of the object token.

sequence diagram

private void levelCheck(CharSource source)

private void levelCheck(CharSource source) {
    nestLevel++;
    if (nestLevel > ParseConstants.NEST_LEVEL) {
        throw new UnexpectedCharacterException("Next level violation", "Too many levels " + nestLevel, source);
    }
}

The method levelCheck in the JsonEventStrictParser class is responsible for checking the nesting level of a JSON document. Here is a step-by-step description of what this method does:

  1. It receives a CharSource object as a parameter, which represents the source of characters for parsing the JSON document.

  2. The method increments the nestLevel variable by one. This variable keeps track of the current nesting level in the JSON document.

  3. It checks if the nestLevel is greater than a constant value ParseConstants.NEST_LEVEL. This constant represents the maximum allowed nesting level in the JSON document.

  4. If the nestLevel exceeds the maximum allowed level, the method throws an UnexpectedCharacterException with the message "Next level violation" and additional information about exceeding the allowed level.

  5. If the nestLevel is within the allowed limit, the method continues execution without any further action.

Overall, the levelCheck method ensures that the nesting level of the JSON document does not exceed a certain threshold and throws an exception if the limit is violated. This check helps maintain the integrity and reliability of the parsing process.

The levelCheck method in the JsonEventStrictParser class is responsible for checking the nesting level of a JSON document.

This method increments the nestLevel variable by one, indicating that a new nested level has been encountered. If the nestLevel exceeds the maximum allowed nesting level defined in ParseConstants.NEST_LEVEL, an UnexpectedCharacterException is thrown, indicating that the JSON document has violated the maximum nesting level constraint.

The exception message includes the details of the violation, specifically mentioning the current nestLevel, and the source of the JSON document where the violation occurred.

sequence diagram

Clone this wiki locally