diff --git a/jmespath-jackson-jr/pom.xml b/jmespath-jackson-jr/pom.xml
new file mode 100644
index 0000000..7362efb
--- /dev/null
+++ b/jmespath-jackson-jr/pom.xml
@@ -0,0 +1,42 @@
+
+
+ 4.0.0
+
+ jmespath-jackson-jr
+ JMESPath Jackson jr
+ A JMESPath implementation for Java
+
+
+ io.burt
+ jmespath
+ 0.5.2-SNAPSHOT
+
+
+
+
+ ${project.groupId}
+ jmespath-core
+ ${project.parent.version}
+
+
+ ${project.groupId}
+ jmespath-core
+ ${project.parent.version}
+ test-jar
+ test
+
+
+ com.fasterxml.jackson.jr
+ jackson-jr-objects
+ 2.14.2
+
+
+ com.fasterxml.jackson.jr
+ jackson-jr-stree
+ 2.14.2
+
+
+
+
\ No newline at end of file
diff --git a/jmespath-jackson-jr/src/main/java/io/burt/jmespath/jacksonjr/JacksonJrRuntime.java b/jmespath-jackson-jr/src/main/java/io/burt/jmespath/jacksonjr/JacksonJrRuntime.java
new file mode 100644
index 0000000..749fe2a
--- /dev/null
+++ b/jmespath-jackson-jr/src/main/java/io/burt/jmespath/jacksonjr/JacksonJrRuntime.java
@@ -0,0 +1,230 @@
+package io.burt.jmespath.jacksonjr;
+
+import com.fasterxml.jackson.core.JsonToken;
+import com.fasterxml.jackson.jr.ob.JSON;
+import com.fasterxml.jackson.jr.stree.JacksonJrsTreeCodec;
+import com.fasterxml.jackson.jr.stree.JrsArray;
+import com.fasterxml.jackson.jr.stree.JrsBoolean;
+import com.fasterxml.jackson.jr.stree.JrsNull;
+import com.fasterxml.jackson.jr.stree.JrsNumber;
+import com.fasterxml.jackson.jr.stree.JrsObject;
+import com.fasterxml.jackson.jr.stree.JrsString;
+import com.fasterxml.jackson.jr.stree.JrsValue;
+import io.burt.jmespath.BaseRuntime;
+import io.burt.jmespath.JmesPathType;
+import io.burt.jmespath.RuntimeConfiguration;
+import java.io.IOException;
+import java.io.UncheckedIOException;
+import java.util.AbstractList;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+public class JacksonJrRuntime extends BaseRuntime {
+ private final JSON json;
+
+ public JacksonJrRuntime() {
+ this(RuntimeConfiguration.defaultConfiguration());
+ }
+
+ public JacksonJrRuntime(RuntimeConfiguration configuration) {
+ this(configuration, JSON.builder()
+ .treeCodec(new JacksonJrsTreeCodec())
+ .build());
+ }
+
+ public JacksonJrRuntime(RuntimeConfiguration configuration, JSON json) {
+ super(configuration);
+ this.json = json;
+ }
+
+ @Override
+ public JrsValue parseString(String str) {
+ try {
+ return json.treeFrom(str);
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ private static class JrsArrayListWrapper extends AbstractList {
+ private final JrsArray array;
+
+ JrsArrayListWrapper(JrsArray array) {
+ this.array = array;
+ }
+
+ @Override
+ public JrsValue get(int index) {
+ return array.get(index);
+ }
+
+ @Override
+ public int size() {
+ return array.size();
+ }
+ }
+
+ @Override
+ public List toList(JrsValue value) {
+ if (value == null) {
+ return Collections.emptyList();
+ } else if (value.isArray()) {
+ return new JrsArrayListWrapper((JrsArray) value);
+ } else if (value.isObject()) {
+ JrsObject object = (JrsObject) value;
+ List list = new ArrayList<>(object.size());
+ Iterator> iterator = object.fields();
+
+ while (iterator.hasNext()) {
+ Map.Entry entry = iterator.next();
+ list.add(entry.getValue());
+ }
+ return list;
+ } else {
+ return Collections.emptyList();
+ }
+ }
+
+ @Override
+ public String toString(JrsValue value) {
+ if (JsonToken.VALUE_STRING.equals(value.asToken())) {
+ return value.asText();
+ } else {
+ try {
+ return json.asString(value);
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
+ }
+
+ @Override
+ public Number toNumber(JrsValue value) {
+ if (value.isValueNode() && value.isNumber()) {
+ JrsNumber number = (JrsNumber) value;
+ return number.getValue();
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public boolean isTruthy(JrsValue value) {
+ if (value.isContainerNode()) {
+ return value.size() > 0;
+ } else if (value.isValueNode()) {
+ switch (value.asToken()) {
+ case VALUE_STRING:
+ return !value.asText().isEmpty();
+ case VALUE_FALSE:
+ case VALUE_NULL:
+ return false;
+ default:
+ return true;
+ }
+ } else {
+ return !value.isMissingNode();
+ }
+ }
+
+ @Override
+ public JmesPathType typeOf(JrsValue value) {
+ switch (value.asToken()) {
+ case START_ARRAY:
+ return JmesPathType.ARRAY;
+ case VALUE_EMBEDDED_OBJECT:
+ case START_OBJECT:
+ return JmesPathType.OBJECT;
+ case VALUE_STRING:
+ return JmesPathType.STRING;
+ case VALUE_NUMBER_INT:
+ case VALUE_NUMBER_FLOAT:
+ return JmesPathType.NUMBER;
+ case VALUE_TRUE:
+ case VALUE_FALSE:
+ return JmesPathType.BOOLEAN;
+ case VALUE_NULL:
+ return JmesPathType.NULL;
+ case NOT_AVAILABLE:
+ default:
+ throw new IllegalStateException(String.format("Unknown node type encountered: %s", value.asToken()));
+ }
+ }
+
+ @Override
+ public JrsValue getProperty(JrsValue value, JrsValue name) {
+ if (JsonToken.VALUE_NULL.equals(value.asToken())) {
+ return JrsNull.instance();
+ } else {
+ JrsValue node = value.get(name.asText());
+ return node != null ? node : createNull();
+ }
+ }
+
+ @Override
+ public Collection getPropertyNames(JrsValue value) {
+ if (value.isObject()) {
+ List names = new ArrayList<>(value.size());
+ Iterator fieldNames = value.fieldNames();
+ while (fieldNames.hasNext()) {
+ names.add(createString(fieldNames.next()));
+ }
+ return names;
+ } else {
+ return Collections.emptyList();
+ }
+ }
+
+ @Override
+ public JrsValue createNull() {
+ return JrsNull.instance();
+ }
+
+ @Override
+ public JrsValue createArray(Collection elements) {
+ List values = new ArrayList<>();
+ for (JrsValue node: elements) {
+ if (node == null) {
+ values.add(JrsNull.instance());
+ } else {
+ values.add(node);
+ }
+ }
+ return new JrsArray(values);
+
+ }
+
+ @Override
+ public JrsValue createString(String str) {
+ return new JrsString(str);
+ }
+
+ @Override
+ public JrsValue createBoolean(boolean b) {
+ return b ? JrsBoolean.TRUE : JrsBoolean.FALSE;
+ }
+
+ @Override
+ public JrsValue createObject(Map obj) {
+ Map values = new HashMap<>();
+ for (Map.Entry entry : obj.entrySet()) {
+ values.put(entry.getKey().asText(), entry.getValue());
+ }
+ return new JrsObject(values);
+ }
+
+ @Override
+ public JrsValue createNumber(double n) {
+ return new JrsNumber(n);
+ }
+
+ @Override
+ public JrsValue createNumber(long n) {
+ return new JrsNumber(n);
+ }
+}
diff --git a/jmespath-jackson-jr/src/test/java/io/burt/jmespath/jacksonjr/JacksonJrComplianceTest.java b/jmespath-jackson-jr/src/test/java/io/burt/jmespath/jacksonjr/JacksonJrComplianceTest.java
new file mode 100644
index 0000000..040f129
--- /dev/null
+++ b/jmespath-jackson-jr/src/test/java/io/burt/jmespath/jacksonjr/JacksonJrComplianceTest.java
@@ -0,0 +1,12 @@
+package io.burt.jmespath.jacksonjr;
+
+import com.fasterxml.jackson.jr.stree.JrsValue;
+import io.burt.jmespath.Adapter;
+import io.burt.jmespath.JmesPathComplianceTest;
+
+public class JacksonJrComplianceTest extends JmesPathComplianceTest {
+ private Adapter runtime = new JacksonJrRuntime();
+
+ @Override
+ protected Adapter runtime() { return runtime; }
+}
diff --git a/jmespath-jackson-jr/src/test/java/io/burt/jmespath/jacksonjr/JacksonJrTest.java b/jmespath-jackson-jr/src/test/java/io/burt/jmespath/jacksonjr/JacksonJrTest.java
new file mode 100644
index 0000000..2c1004f
--- /dev/null
+++ b/jmespath-jackson-jr/src/test/java/io/burt/jmespath/jacksonjr/JacksonJrTest.java
@@ -0,0 +1,14 @@
+package io.burt.jmespath.jacksonjr;
+
+
+import com.fasterxml.jackson.jr.stree.JrsValue;
+import io.burt.jmespath.Adapter;
+import io.burt.jmespath.JmesPathRuntimeTest;
+import io.burt.jmespath.RuntimeConfiguration;
+
+public class JacksonJrTest extends JmesPathRuntimeTest {
+ @Override
+ protected Adapter createRuntime(RuntimeConfiguration configuration) {
+ return new JacksonJrRuntime(configuration);
+ }
+}