Skip to content

Commit 3ca2b83

Browse files
committed
Add json-java21-jsonpath-codegen module: bytecode-generated JsonPath queries
Compiles JsonPath expressions into Java 21 classfiles via the JDK 24+ ClassFile API. Generated code eliminates interpretation overhead by inlining all segment dispatch at codegen time. Supports all 8 segment types: PropertyAccess, ArrayIndex, ArraySlice, Wildcard, RecursiveDescent, Filter, Union, ScriptExpression. Uses runtime helpers for recursive descent (DFS traversal) and filter comparison (value extraction and comparison logic). 29 cross-validation tests verify codegen produces identical results to the interpreter for all supported JsonPath expressions. Also makes JsonPathAst public and adds JsonPath.ast() accessor for cross-module codegen access. To verify: mvn test -pl json-java21-jsonpath-codegen -am
1 parent f629733 commit 3ca2b83

File tree

14 files changed

+1507
-1
lines changed

14 files changed

+1507
-1
lines changed
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
5+
http://maven.apache.org/xsd/maven-4.0.0.xsd">
6+
<modelVersion>4.0.0</modelVersion>
7+
8+
<parent>
9+
<groupId>io.github.simbo1905.json</groupId>
10+
<artifactId>parent</artifactId>
11+
<version>0.1.9</version>
12+
</parent>
13+
14+
<artifactId>java.util.json.jsonpath.codegen</artifactId>
15+
<packaging>jar</packaging>
16+
<name>java.util.json Java21 Backport JsonPath Codegen</name>
17+
<url>https://simbo1905.github.io/java.util.json.Java21/</url>
18+
<scm>
19+
<connection>scm:git:https://github.com/simbo1905/java.util.json.Java21.git</connection>
20+
<developerConnection>scm:git:git@github.com:simbo1905/java.util.json.Java21.git</developerConnection>
21+
<url>https://github.com/simbo1905/java.util.json.Java21</url>
22+
<tag>HEAD</tag>
23+
</scm>
24+
<description>Bytecode-generated JsonPath query functions using the JDK 24+ ClassFile API.
25+
Compiles JsonPath expressions into Java 21 compatible classfiles for hot-path evaluation.
26+
Optional dependency: falls back to the interpreter path when absent.</description>
27+
28+
<properties>
29+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
30+
<maven.compiler.release>24</maven.compiler.release>
31+
</properties>
32+
33+
<dependencies>
34+
<dependency>
35+
<groupId>io.github.simbo1905.json</groupId>
36+
<artifactId>java.util.json</artifactId>
37+
<version>${project.version}</version>
38+
</dependency>
39+
<dependency>
40+
<groupId>io.github.simbo1905.json</groupId>
41+
<artifactId>java.util.json.jsonpath</artifactId>
42+
<version>${project.version}</version>
43+
</dependency>
44+
45+
<!-- Test dependencies -->
46+
<dependency>
47+
<groupId>org.junit.jupiter</groupId>
48+
<artifactId>junit-jupiter-api</artifactId>
49+
<scope>test</scope>
50+
</dependency>
51+
<dependency>
52+
<groupId>org.junit.jupiter</groupId>
53+
<artifactId>junit-jupiter-engine</artifactId>
54+
<scope>test</scope>
55+
</dependency>
56+
<dependency>
57+
<groupId>org.junit.jupiter</groupId>
58+
<artifactId>junit-jupiter-params</artifactId>
59+
<scope>test</scope>
60+
</dependency>
61+
<dependency>
62+
<groupId>org.assertj</groupId>
63+
<artifactId>assertj-core</artifactId>
64+
<scope>test</scope>
65+
</dependency>
66+
</dependencies>
67+
68+
<build>
69+
<plugins>
70+
<plugin>
71+
<groupId>org.apache.maven.plugins</groupId>
72+
<artifactId>maven-compiler-plugin</artifactId>
73+
<version>3.13.0</version>
74+
<configuration>
75+
<release>24</release>
76+
<compilerArgs>
77+
<arg>-Xlint:all</arg>
78+
<arg>-Xdiags:verbose</arg>
79+
</compilerArgs>
80+
</configuration>
81+
</plugin>
82+
<plugin>
83+
<groupId>org.apache.maven.plugins</groupId>
84+
<artifactId>maven-javadoc-plugin</artifactId>
85+
<configuration>
86+
<release>24</release>
87+
<doclint>none</doclint>
88+
</configuration>
89+
</plugin>
90+
<plugin>
91+
<groupId>org.apache.maven.plugins</groupId>
92+
<artifactId>maven-surefire-plugin</artifactId>
93+
<configuration>
94+
<argLine>-ea</argLine>
95+
<systemPropertyVariables>
96+
<java.util.logging.ConsoleHandler.level>${java.util.logging.ConsoleHandler.level}</java.util.logging.ConsoleHandler.level>
97+
</systemPropertyVariables>
98+
</configuration>
99+
</plugin>
100+
</plugins>
101+
</build>
102+
</project>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package json.java21.jsonpath.codegen;
2+
3+
import jdk.sandbox.java.util.json.JsonValue;
4+
import java.util.List;
5+
6+
/// A compiled JsonPath query that executes against a JSON document.
7+
///
8+
/// Generated implementations contain bytecode-inlined evaluation logic
9+
/// with no interpretation overhead. The generated classfiles target Java 21.
10+
public interface CompiledJsonPath {
11+
12+
/// Evaluates this JsonPath expression against the given JSON document.
13+
///
14+
/// @param root the root JSON document to query
15+
/// @return a list of matched JSON values (never null, may be empty)
16+
List<JsonValue> query(JsonValue root);
17+
18+
/// Returns the original JsonPath expression string.
19+
///
20+
/// @return the JsonPath expression this was compiled from
21+
@Override
22+
String toString();
23+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package json.java21.jsonpath.codegen;
2+
3+
import java.lang.constant.ClassDesc;
4+
import java.lang.constant.ConstantDescs;
5+
import java.lang.constant.MethodTypeDesc;
6+
7+
/// Shared class descriptors and method type descriptors for bytecode emission.
8+
///
9+
/// All fields are compile-time constants referencing the types the generated
10+
/// classfiles interact with at runtime (JSON API, collections, JDK stdlib).
11+
final class Descriptors {
12+
13+
private Descriptors() {}
14+
15+
// -- JDK types --
16+
static final ClassDesc CD_Object = ConstantDescs.CD_Object;
17+
static final ClassDesc CD_String = ConstantDescs.CD_String;
18+
19+
// -- Collections --
20+
static final ClassDesc CD_ArrayList = ClassDesc.of("java.util.ArrayList");
21+
static final ClassDesc CD_List = ClassDesc.of("java.util.List");
22+
static final ClassDesc CD_Map = ClassDesc.of("java.util.Map");
23+
static final ClassDesc CD_MapEntry = ClassDesc.of("java.util.Map$Entry");
24+
static final ClassDesc CD_Set = ClassDesc.of("java.util.Set");
25+
static final ClassDesc CD_Iterator = ClassDesc.of("java.util.Iterator");
26+
static final ClassDesc CD_Collection = ClassDesc.of("java.util.Collection");
27+
28+
// -- JSON API types --
29+
static final ClassDesc CD_JsonValue = ClassDesc.of("jdk.sandbox.java.util.json.JsonValue");
30+
static final ClassDesc CD_JsonObject = ClassDesc.of("jdk.sandbox.java.util.json.JsonObject");
31+
static final ClassDesc CD_JsonArray = ClassDesc.of("jdk.sandbox.java.util.json.JsonArray");
32+
static final ClassDesc CD_JsonString = ClassDesc.of("jdk.sandbox.java.util.json.JsonString");
33+
static final ClassDesc CD_JsonNumber = ClassDesc.of("jdk.sandbox.java.util.json.JsonNumber");
34+
static final ClassDesc CD_JsonBoolean = ClassDesc.of("jdk.sandbox.java.util.json.JsonBoolean");
35+
static final ClassDesc CD_JsonNull = ClassDesc.of("jdk.sandbox.java.util.json.JsonNull");
36+
37+
// -- JsonPath codegen types --
38+
static final ClassDesc CD_CompiledJsonPath = ClassDesc.of("json.java21.jsonpath.codegen.CompiledJsonPath");
39+
static final ClassDesc CD_RecursiveDescentHelper = ClassDesc.of("json.java21.jsonpath.codegen.RecursiveDescentHelper");
40+
41+
// -- Common method type descriptors --
42+
static final MethodTypeDesc MTD_String = MethodTypeDesc.of(CD_String);
43+
static final MethodTypeDesc MTD_boolean = MethodTypeDesc.of(ConstantDescs.CD_boolean);
44+
static final MethodTypeDesc MTD_int = MethodTypeDesc.of(ConstantDescs.CD_int);
45+
static final MethodTypeDesc MTD_double = MethodTypeDesc.of(ConstantDescs.CD_double);
46+
static final MethodTypeDesc MTD_long = MethodTypeDesc.of(ConstantDescs.CD_long);
47+
static final MethodTypeDesc MTD_boolean_Object = MethodTypeDesc.of(ConstantDescs.CD_boolean, CD_Object);
48+
static final MethodTypeDesc MTD_Object_Object = MethodTypeDesc.of(CD_Object, CD_Object);
49+
static final MethodTypeDesc MTD_Object_int = MethodTypeDesc.of(CD_Object, ConstantDescs.CD_int);
50+
static final MethodTypeDesc MTD_void_String = MethodTypeDesc.of(ConstantDescs.CD_void, CD_String);
51+
static final MethodTypeDesc MTD_Map = MethodTypeDesc.of(CD_Map);
52+
static final MethodTypeDesc MTD_List = MethodTypeDesc.of(CD_List);
53+
static final MethodTypeDesc MTD_List_JsonValue = MethodTypeDesc.of(CD_List, CD_JsonValue);
54+
static final MethodTypeDesc MTD_Set = MethodTypeDesc.of(CD_Set);
55+
static final MethodTypeDesc MTD_Iterator = MethodTypeDesc.of(CD_Iterator);
56+
static final MethodTypeDesc MTD_Object = MethodTypeDesc.of(CD_Object);
57+
static final MethodTypeDesc MTD_String_String = MethodTypeDesc.of(CD_String, CD_String);
58+
static final MethodTypeDesc MTD_String_int = MethodTypeDesc.of(CD_String, ConstantDescs.CD_int);
59+
60+
// -- RecursiveDescentHelper method descriptors --
61+
static final MethodTypeDesc MTD_void_JsonValue_String_List = MethodTypeDesc.of(
62+
ConstantDescs.CD_void, CD_JsonValue, CD_String, CD_List);
63+
static final MethodTypeDesc MTD_void_JsonValue_List = MethodTypeDesc.of(
64+
ConstantDescs.CD_void, CD_JsonValue, CD_List);
65+
}

0 commit comments

Comments
 (0)