A robust, hand-written JSON parser implemented in Java, following an incremental development methodology.
This project implements a complete JSON parser from scratch. It performs lexical analysis (tokenization) and syntax analysis (parsing) to construct an Abstract Syntax Tree (AST) representing the parsed JSON structure.
The implementation is inspired by the principles of compiler construction, specifically following the incremental approach often found in literature like Terence Parr's "Implementing Compilers". The development progressed through several "Steps," each increasing the complexity of the supported JSON grammar (from basic primitives to nested objects and arrays).
The parser is divided into three main components:
The JsonLexer scans the input string and converts it into a stream of Token objects. It handles:
- Whitespace skipping.
- Identifying JSON primitives (strings, numbers, booleans, null).
- Recognizing structural characters (
{,},[,],:,,). - Handling escape sequences within strings.
The JsonParser consumes the token stream and applies the JSON grammar rules. It uses a recursive descent parsing strategy to build the tree structure.
The parser produces a heterogeneous AST using a JsonNode interface. This allows for a type-safe and expressive representation of the JSON data:
JsonArrayNode: Represents a JSON array (contains aList<JsonNode>).JsonObjectNode: Represents a JSON object (contains aMap<String, JsonNode>).JsonStringNode: Represents a JSON string.JsonNumberNode: Represents a JSON number.JsonBooleanNode: Represents a JSON boolean (true/false).JsonNullNode: Represents a JSONnull.
- Java 21 or higher.
- Apache Maven installed.
To compile the source code, run:
mvn clean compileThe project is extensively tested using JUnit 5. To run the full suite of tests:
mvn testWhile the project currently utilizes Maven, it was originally developed with a manual, step-based testing approach. The following roadmap outlines the transition to a modern, automated development workflow:
- Current: Uses a mix of JUnit 5 and manual shell scripts (
valid.sh,invalid.sh, etc.) to verify specific parsing steps. - Goal: Consolidate all validation into the JUnit 5 suite. Use parameterized tests to handle the large volume of JSON test files in
src/test/resources.
- Goal: Implement GitHub Actions to automatically run the Maven test suite on every
pushandpull_request. This ensures that new changes do not break existing parsing logic.
- Goal: Integrate a Java formatter (such as
google-java-format) via themaven-checkstyle-pluginorspotless-maven-plugin. This ensures consistent code style across the project.
- Goal: Once the learning/challenge phase is complete, the "Step" classes (e.g.,
Step1.java,Step3.java) should be removed in favor of a single, clean, production-ready implementation.
.
├── pom.xml # Maven configuration
├── src
│ ├── main
│ │ ├── java
│ │ │ └── it/diamondnet/challenge/
│ │ │ ├── JsonLexer.java # Lexical analyzer
│ │ │ ├── JsonParser.java # Syntax analyzer
│ │ │ ├── JsonNode.java # AST Interface
│ │ │ └── ... (AST Implementations)
│ │ └── resources # Grammar definitions and images
│ └── test
│ ├── java
│ │ └── it/diamondnet/challenge/ # JUnit 5 tests
│ └── resources # JSON test files (organized by steps)
└── target # Compiled classes and reports
This project is for educational purposes, following the Coding Challenges guidelines.