Problem
jjq-core is compiled with <release>22</release>, which means any project that wants to use JqValue as a data type must also target Java 22+. This prevents adoption in ecosystems with older Java baselines.
Concrete use case: We are building a Jenkins plugin for h5m (the next-generation Horreum). Jenkins requires Java 17 (as of Jenkins 2.479+). The plugin needs to send and receive JSON data from h5m's REST API, which uses JqValue as its JSON representation. Ideally the plugin would use JqValue directly for type safety and to avoid a separate JSON library (Jackson) in the data path. However, the plugin cannot depend on jjq-core because the compiled bytecode requires Java 22, while Jenkins runs on Java 17.
Analysis
I audited the value types in io.hyperfoil.tools.jjq.value (JqValue, JqNull, JqBoolean, JqNumber, JqString, JqArray, JqObject, JqValues, JqTypeError, BytOutput, SwarUtil). The language features they use are:
| Feature |
Java version (final) |
Used in |
sealed interface + permits |
Java 17 |
JqValue.java:8-9 |
record |
Java 16 |
JqObject.java:543 (MergeFrame) |
Pattern matching for instanceof |
Java 16 |
JqString.java, JqValues.java (multiple sites) |
List.getFirst() / List.getLast() |
Java 21 (SequencedCollection) |
JqArray.java:164,167,275 (3 call sites) |
The only API requiring Java 21+ is List.getFirst()/getLast() — 3 call sites in JqArray.java. These can be trivially replaced with list.get(0) and list.get(list.size() - 1) without any performance impact (ArrayList random access is O(1)).
All imports in the value types come from java.base (java.math, java.util, java.io, java.nio, java.lang.invoke). There are zero external runtime dependencies.
The jq engine code (lexer, parser, AST, evaluator, builtins, VM) likely uses Java 22+ features more extensively and should stay at Java 22.
Proposal
Extract a jjq-value module containing only the value type classes from io.hyperfoil.tools.jjq.value:
jjq-value/
src/main/java/io/hyperfoil/tools/jjq/value/
JqValue.java
JqNull.java
JqBoolean.java
JqNumber.java
JqString.java
JqArray.java
JqObject.java
JqValues.java
JqTypeError.java
BytOutput.java
SwarUtil.java
With:
<maven.compiler.release>17</maven.compiler.release>
jjq-core depends on jjq-value (the engine uses these types)
- Replace 3x
List.getFirst()/getLast() calls in JqArray.java with Java 17-compatible equivalents
Constraints
- Must not affect performance. The replacement for
getFirst()/getLast() is get(0)/get(size()-1) on ArrayList, which has identical performance (both are O(1) direct array index access — getFirst()/getLast() are just convenience methods added in Java 21).
- No API changes to any value type.
jjq-core continues at Java 22 — only the value types module drops to Java 17.
Benefits
- Jenkins plugins, Gradle plugins, and other Java 17+ tools can use
JqValue as a JSON data type
- h5m's REST API consumers get type-safe JSON handling without needing Java 22
- Zero-dependency value types module (
jjq-value has no transitive deps, same as today)
- The
jjq-jackson, jjq-jakarta, and jjq-fastjson2 adapter modules can also lower their Java requirement since they primarily bridge external libraries to JqValue
Problem
jjq-coreis compiled with<release>22</release>, which means any project that wants to useJqValueas a data type must also target Java 22+. This prevents adoption in ecosystems with older Java baselines.Concrete use case: We are building a Jenkins plugin for h5m (the next-generation Horreum). Jenkins requires Java 17 (as of Jenkins 2.479+). The plugin needs to send and receive JSON data from h5m's REST API, which uses
JqValueas its JSON representation. Ideally the plugin would useJqValuedirectly for type safety and to avoid a separate JSON library (Jackson) in the data path. However, the plugin cannot depend onjjq-corebecause the compiled bytecode requires Java 22, while Jenkins runs on Java 17.Analysis
I audited the value types in
io.hyperfoil.tools.jjq.value(JqValue,JqNull,JqBoolean,JqNumber,JqString,JqArray,JqObject,JqValues,JqTypeError,BytOutput,SwarUtil). The language features they use are:sealed interface+permitsJqValue.java:8-9recordJqObject.java:543(MergeFrame)instanceofJqString.java,JqValues.java(multiple sites)List.getFirst()/List.getLast()SequencedCollection)JqArray.java:164,167,275(3 call sites)The only API requiring Java 21+ is
List.getFirst()/getLast()— 3 call sites inJqArray.java. These can be trivially replaced withlist.get(0)andlist.get(list.size() - 1)without any performance impact (ArrayList random access is O(1)).All imports in the value types come from
java.base(java.math,java.util,java.io,java.nio,java.lang.invoke). There are zero external runtime dependencies.The jq engine code (lexer, parser, AST, evaluator, builtins, VM) likely uses Java 22+ features more extensively and should stay at Java 22.
Proposal
Extract a
jjq-valuemodule containing only the value type classes fromio.hyperfoil.tools.jjq.value:With:
<maven.compiler.release>17</maven.compiler.release>jjq-coredepends onjjq-value(the engine uses these types)List.getFirst()/getLast()calls inJqArray.javawith Java 17-compatible equivalentsConstraints
getFirst()/getLast()isget(0)/get(size()-1)onArrayList, which has identical performance (both are O(1) direct array index access —getFirst()/getLast()are just convenience methods added in Java 21).jjq-corecontinues at Java 22 — only the value types module drops to Java 17.Benefits
JqValueas a JSON data typejjq-valuehas no transitive deps, same as today)jjq-jackson,jjq-jakarta, andjjq-fastjson2adapter modules can also lower their Java requirement since they primarily bridge external libraries toJqValue