Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 39 additions & 9 deletions json-java21-jsonpath/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,43 @@ This file is for contributor/agent operational notes. Read `json-java21-jsonpath
- User docs MUST recommend only `./mvnw`.
- The `$(command -v mvnd || command -v mvn || command -v ./mvnw)` wrapper is for local developer speed only; do not put it in user-facing docs.

Stable code entry points:
- `json-java21-jsonpath/src/main/java/json/java21/jsonpath/JsonPath.java`
- `json-java21-jsonpath/src/main/java/json/java21/jsonpath/JsonPathParser.java`
- `json-java21-jsonpath/src/main/java/json/java21/jsonpath/JsonPathAst.java`
- `json-java21-jsonpath/src/main/java/json/java21/jsonpath/JsonPathParseException.java`
- `json-java21-jsonpath/src/main/java/json/java21/jsonpath/JsonPathStreams.java`

When changing syntax/behavior:
- Update `JsonPathAst` + `JsonPathParser` + `JsonPath` together.
## Architecture

JsonPath is a sealed interface with two implementations:
- `JsonPathInterpreted`: AST-walking interpreter (default from `JsonPath.parse()`)
- `JsonPathCompiled`: Bytecode-compiled version (from `JsonPath.compile()`)

The compilation flow:
1. `JsonPath.parse()` -> `JsonPathInterpreted` (fast parsing, AST-based evaluation)
2. `JsonPath.compile()` -> `JsonPathCompiled` (generates Java source, compiles with JDK ToolProvider)

## Stable Code Entry Points

- `json-java21-jsonpath/src/main/java/json/java21/jsonpath/JsonPath.java` - Public sealed interface
- `json-java21-jsonpath/src/main/java/json/java21/jsonpath/JsonPathParser.java` - Parses expressions to AST
- `json-java21-jsonpath/src/main/java/json/java21/jsonpath/JsonPathAst.java` - AST node definitions
- `json-java21-jsonpath/src/main/java/json/java21/jsonpath/JsonPathInterpreted.java` - AST-walking evaluator
- `json-java21-jsonpath/src/main/java/json/java21/jsonpath/JsonPathCompiler.java` - Code generator and compiler
- `json-java21-jsonpath/src/main/java/json/java21/jsonpath/JsonPathCompiled.java` - Compiled executor wrapper
- `json-java21-jsonpath/src/main/java/json/java21/jsonpath/JsonPathExecutor.java` - Public interface for generated executors
- `json-java21-jsonpath/src/main/java/json/java21/jsonpath/JsonPathHelpers.java` - Helpers for generated code
- `json-java21-jsonpath/src/main/java/json/java21/jsonpath/JsonPathStreams.java` - Stream processing utilities

## When Changing Syntax/Behavior

- Update `JsonPathAst` + `JsonPathParser` + `JsonPathInterpreted` together.
- Update `JsonPathCompiler` code generation to match any AST changes.
- Add parser + evaluation tests; new tests should extend `JsonPathLoggingConfig`.
- Add compiler tests in `JsonPathCompilerTest` to verify compiled and interpreted produce identical results.

## Code Generation Notes

The `JsonPathCompiler` generates Java source code that:
- Imports from `jdk.sandbox.java.util.json.*` and `json.java21.jsonpath.*`
- Implements `JsonPathExecutor` functional interface
- Uses `JsonPathHelpers` for complex operations (recursive descent, comparisons)
- Is compiled in-memory using `javax.tools.ToolProvider`

When adding new AST node types:
1. Add the case to `generateSegmentEvaluation()` in `JsonPathCompiler`
2. Consider if a helper method in `JsonPathHelpers` would simplify the generated code
51 changes: 51 additions & 0 deletions json-java21-jsonpath/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,57 @@ This implementation follows Goessner-style JSONPath operators, including:
- `[?(@.prop)]` and `[?(@.prop op value)]` basic filters
- `[(@.length-1)]` limited script support

## Runtime Compilation (Performance Optimization)

For performance-critical code paths, you can compile a parsed JsonPath to bytecode:

```java
// Parse once, compile for best performance
JsonPath compiled = JsonPath.compile(JsonPath.parse("$.store.book[*].author"));

// Reuse the compiled path for many documents
for (JsonValue doc : documents) {
List<JsonValue> results = compiled.query(doc);
// process results...
}
```

### How It Works

The `JsonPath.compile()` method:
1. Takes a parsed (interpreted) JsonPath
2. Generates optimized Java source code
3. Compiles it to bytecode using the JDK compiler API (`javax.tools.ToolProvider`)
4. Returns a compiled JsonPath that executes as native bytecode

### When to Use Compilation

- **Hot paths**: Use `compile()` when the same path will be executed many times
- **One-off queries**: Use `parse()` directly for single-use paths (compilation overhead isn't worth it)
- **JRE environments**: Compilation requires a JDK; if unavailable, use interpreted paths

### Compilation is Idempotent

Calling `compile()` on an already-compiled path returns the same instance:

```java
JsonPath interpreted = JsonPath.parse("$.store");
JsonPath compiled = JsonPath.compile(interpreted);
JsonPath sameCompiled = JsonPath.compile(compiled); // Returns same instance

// Check if a path is compiled
boolean isCompiled = compiled.isCompiled();
boolean isInterpreted = interpreted.isInterpreted();
```

### Supported Features in Compiled Mode

All JsonPath features are supported in compiled mode:
- Property access, array indices, slices, wildcards
- Recursive descent (`$..property`)
- Filters with comparisons and logical operators
- Unions and limited script expressions (e.g., `[(@.length-1)]`)

## Stream-Based Functions (Aggregations)

Some JsonPath implementations include aggregation functions such as `$.numbers.avg()`.
Expand Down
Loading
Loading