json-parser is a from-scratch JSON lexer and recursive-descent parser written entirely in Java, with no external runtime dependencies. It validates JSON documents for well-formedness against the JSON grammar and reports the result through a Unix-style exit code.
This project was built as part of the Build Your Own JSON Parser Challenge.
Explore the docs · Report Bug · LinkedIn · Email
- Full JSON grammar coverage: objects, arrays, strings (with escape-sequence and
\uXXXXunicode validation), numbers (integers, decimals, exponents), and thetrue/false/nullkeywords. - Line/column-accurate error reporting: every
JsonParseExceptioncarries the exact line and column of the offending token, not just "somewhere in the file." - Nesting depth guard: both objects and arrays protect their own recursion against a configurable
MAX_DEPTH, so pathological input fails with a cleanJsonParseExceptioninstead of an uncaughtStackOverflowError. - Unix-style CLI: exits
0for valid JSON,1for invalid JSON or I/O errors, with a matching message onstdout/stderr. - Verified against the reference suite: passes the full official json.org
JSON_checkertest suite (36/36 fixtures) alongside a hand-written JUnit 5 suite.
- Java Development Kit (JDK) 24 or higher.
- Maven on your
PATH(no wrapper is committed to this repo).
-
Clone the repository:
git clone https://github.com/MohammadRokib/json-parser-java.git cd json-parser-java -
Compile, test, and package with Maven:
mvn clean package
This runs the full test suite and produces
target/json-parser-1.0-SNAPSHOT.jar.
The jar has no Main-Class configured in its manifest yet, so it's run by pointing java at the jar with -cp and the fully-qualified entry class.
java -cp target/json-parser-1.0-SNAPSHOT.jar org.example.jsonparser.JsonParser <file.json>1. Valid JSON:
$ java -cp target/json-parser-1.0-SNAPSHOT.jar org.example.jsonparser.JsonParser valid.json
Valid JSON
$ echo $?
02. Invalid JSON, with a precise error location:
$ java -cp target/json-parser-1.0-SNAPSHOT.jar org.example.jsonparser.JsonParser invalid.json
Invalid JSON: Expected a value but found RBRACE at line 1 column 7
$ echo $?
1Parsing is split into the classic two-stage pipeline: lexical analysis, then syntactic analysis.
source text → Reader → Lexer.nextToken() → Token(TokenType, lexeme, line, column) → Parser → valid/invalid → JsonParser (CLI)
Lexer.java: streams the input one character at a time through a plainjava.io.Reader(no pushback/lookahead buffering needed - one character of internal state is enough) and turns it into a stream ofTokens: braces, brackets, colon, comma, strings, numbers, and keywords. Tracksline/columnas it advances so every downstream error can point at an exact location.Token.java/TokenType.java: an immutablerecord Token(TokenType type, String lexeme, int line, int column)and a flat enum of the token kinds plusEOF.Parser.java: a recursive-descent parser (parseObject,parseArray,parsePairs,parseValue) that walks the token stream and validates it against the JSON grammar. BothparseObjectandparseArrayguard their own entry againstMAX_DEPTH, so deeply nested input of either kind fails cleanly instead of exhausting the JVM stack.JsonParseException.java: an unchecked exception that always carriesline/column, so every failure - from the lexer or the parser - reports exactly where it happened.JsonParser.java: the CLI entry point. Reads a file path argument, wiresLexer→Parser, and translates the outcome intoValid JSON/Invalid JSON: <reason>plus the matching exit code.
Design note: this parser validates syntax - it does not build a JSON value tree (no JsonObject/JsonArray/etc. is ever constructed). That matches the actual contract of the Coding Challenges JSON Parser spec, whose only observable requirement at every step is "report valid or invalid, with the right exit code" - not "return usable parsed data."
mvn testThe suite (90 tests, JUnit 5) is split across:
LexerTest,LexerStringTest,LexerNumberTest,LexerKeywordTest: token-level unit tests, largely@ParameterizedTest-driven.ParserTest: grammar-level tests for valid and invalid JSON snippets, including nested objects/arrays.OfficialSuiteTest: runs every fixture insrc/test/resources/json_checker(the official json.orgpass*.json/fail*.jsonsuite) and asserts the parser accepts/rejects each one correctly - the strongest correctness signal in the repo, since it's an independent external reference suite rather than a test the author wrote for their own implementation.
Mohammad Rokib