Skip to content
Merged
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
30 changes: 5 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# JMESPath.cr

A Crystal implementation of [JMESPath](https://jmespath.org/), a query language for JSON. JMESPath allows you to declaratively extract elements from complex JSON documents.
A fully compliant Crystal implementation of [JMESPath](https://jmespath.org/), a query language for JSON. JMESPath allows you to declaratively extract elements from complex JSON documents.

## Installation

Expand Down Expand Up @@ -91,7 +91,7 @@ JMESPath.search("map(&name, people)", data) # => ["bob", "alice"]

## Features

The library supports most JMESPath expressions including:
Full JMESPath specification support including:
- Basic field access
- Array indexing and slicing
- List and hash projections
Expand All @@ -106,29 +106,9 @@ The library supports most JMESPath expressions including:

## TODO

The following features are still pending implementation:

1. ~~Built-in Functions~~ (done in v0.3.0)

2. ~~Expression References (expref)~~ (done in v0.3.0)

3. JMESPath Compliance
- Need to implement comprehensive compliance test suite
- Verify behavior matches official JMESPath specification

4. Options Implementation
- Add support for runtime configuration options
- Implementation of custom function registration

5. Caching System Improvements
- Current basic caching system for parsed expressions
- Need to add cache size limits and eviction policies

6. Performance Optimizations
- Optimize parser for large expressions
- Add benchmarking suite

7. ~~Error Handling Improvements~~ (done in v0.3.0)
- Options Implementation: runtime configuration, custom function registration
- Caching System Improvements: cache size limits and eviction policies
- Performance Optimizations: benchmarking suite

## Development

Expand Down
2 changes: 1 addition & 1 deletion shard.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: jmespath
version: 0.3.0
version: 1.0.0

description: |
A Crystal implementation of JMESPath - JSON Query Language
Expand Down
96 changes: 96 additions & 0 deletions spec/compliance/basic.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
[{
"given":
{"foo": {"bar": {"baz": "correct"}}},
"cases": [
{
"expression": "foo",
"result": {"bar": {"baz": "correct"}}
},
{
"expression": "foo.bar",
"result": {"baz": "correct"}
},
{
"expression": "foo.bar.baz",
"result": "correct"
},
{
"expression": "foo\n.\nbar\n.baz",
"result": "correct"
},
{
"expression": "foo.bar.baz.bad",
"result": null
},
{
"expression": "foo.bar.bad",
"result": null
},
{
"expression": "foo.bad",
"result": null
},
{
"expression": "bad",
"result": null
},
{
"expression": "bad.morebad.morebad",
"result": null
}
]
},
{
"given":
{"foo": {"bar": ["one", "two", "three"]}},
"cases": [
{
"expression": "foo",
"result": {"bar": ["one", "two", "three"]}
},
{
"expression": "foo.bar",
"result": ["one", "two", "three"]
}
]
},
{
"given": ["one", "two", "three"],
"cases": [
{
"expression": "one",
"result": null
},
{
"expression": "two",
"result": null
},
{
"expression": "three",
"result": null
},
{
"expression": "one.two",
"result": null
}
]
},
{
"given":
{"foo": {"1": ["one", "two", "three"], "-1": "bar"}},
"cases": [
{
"expression": "foo.\"1\"",
"result": ["one", "two", "three"]
},
{
"expression": "foo.\"1\"[0]",
"result": "one"
},
{
"expression": "foo.\"-1\"",
"result": "bar"
}
]
}
]
148 changes: 148 additions & 0 deletions spec/compliance/benchmarks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
[
{
"given": {
"long_name_for_a_field": true,
"a": {
"b": {
"c": {
"d": {
"e": {
"f": {
"g": {
"h": {
"i": {
"j": {
"k": {
"l": {
"m": {
"n": {
"o": {
"p": true
}
}
}
}
}
}
}
}
}
}
}
}
}
}
},
"b": true,
"c": {
"d": true
}
},
"cases": [
{
"comment": "simple field",
"expression": "b",
"result": true,
"bench": "full"
},
{
"comment": "simple subexpression",
"expression": "c.d",
"result": true,
"bench": "full"
},
{
"comment": "deep field selection no match",
"expression": "a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s",
"result": null,
"bench": "full"
},
{
"comment": "deep field selection",
"expression": "a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p",
"result": true,
"bench": "full"
},
{
"comment": "simple or",
"expression": "not_there || b",
"result": true,
"bench": "full"
}
]
},
{
"given": {
"a":0,"b":1,"c":2,"d":3,"e":4,"f":5,"g":6,"h":7,"i":8,"j":9,"k":10,
"l":11,"m":12,"n":13,"o":14,"p":15,"q":16,"r":17,"s":18,"t":19,"u":20,
"v":21,"w":22,"x":23,"y":24,"z":25
},
"cases": [
{
"comment": "deep ands",
"expression": "a && b && c && d && e && f && g && h && i && j && k && l && m && n && o && p && q && r && s && t && u && v && w && x && y && z",
"result": 25,
"bench": "full"
},
{
"comment": "deep ors",
"expression": "z || y || x || w || v || u || t || s || r || q || p || o || n || m || l || k || j || i || h || g || f || e || d || c || b || a",
"result": 25,
"bench": "full"
},
{
"comment": "lots of summing",
"expression": "sum([z, y, x, w, v, u, t, s, r, q, p, o, n, m, l, k, j, i, h, g, f, e, d, c, b, a])",
"result": 325,
"bench": "full"
},
{
"comment": "lots of function application",
"expression": "sum([z, sum([y, sum([x, sum([w, sum([v, sum([u, sum([t, sum([s, sum([r, sum([q, sum([p, sum([o, sum([n, sum([m, sum([l, sum([k, sum([j, sum([i, sum([h, sum([g, sum([f, sum([e, sum([d, sum([c, sum([b, a])])])])])])])])])])])])])])])])])])])])])])])])])",
"result": 325,
"bench": "full"
},
{
"comment": "lots of multi list",
"expression": "[z, y, x, w, v, u, t, s, r, q, p, o, n, m, l, k, j, i, h, g, f, e, d, c, b, a]",
"result": [25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0],
"bench": "full"
}
]
},
{
"given": {},
"cases": [
{
"comment": "field 50",
"expression": "j49.j48.j47.j46.j45.j44.j43.j42.j41.j40.j39.j38.j37.j36.j35.j34.j33.j32.j31.j30.j29.j28.j27.j26.j25.j24.j23.j22.j21.j20.j19.j18.j17.j16.j15.j14.j13.j12.j11.j10.j9.j8.j7.j6.j5.j4.j3.j2.j1.j0",
"bench": "parse"
},
{
"comment": "pipe 50",
"expression": "j49|j48|j47|j46|j45|j44|j43|j42|j41|j40|j39|j38|j37|j36|j35|j34|j33|j32|j31|j30|j29|j28|j27|j26|j25|j24|j23|j22|j21|j20|j19|j18|j17|j16|j15|j14|j13|j12|j11|j10|j9|j8|j7|j6|j5|j4|j3|j2|j1|j0",
"bench": "parse"
},
{
"comment": "index 50",
"expression": "[49][48][47][46][45][44][43][42][41][40][39][38][37][36][35][34][33][32][31][30][29][28][27][26][25][24][23][22][21][20][19][18][17][16][15][14][13][12][11][10][9][8][7][6][5][4][3][2][1][0]",
"bench": "parse"
},
{
"comment": "long raw string literal",
"expression": "'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz'",
"bench": "parse"
},
{
"comment": "deep projection 104",
"expression": "a[*].b[*].c[*].d[*].e[*].f[*].g[*].h[*].i[*].j[*].k[*].l[*].m[*].n[*].o[*].p[*].q[*].r[*].s[*].t[*].u[*].v[*].w[*].x[*].y[*].z[*].a[*].b[*].c[*].d[*].e[*].f[*].g[*].h[*].i[*].j[*].k[*].l[*].m[*].n[*].o[*].p[*].q[*].r[*].s[*].t[*].u[*].v[*].w[*].x[*].y[*].z[*].a[*].b[*].c[*].d[*].e[*].f[*].g[*].h[*].i[*].j[*].k[*].l[*].m[*].n[*].o[*].p[*].q[*].r[*].s[*].t[*].u[*].v[*].w[*].x[*].y[*].z[*].a[*].b[*].c[*].d[*].e[*].f[*].g[*].h[*].i[*].j[*].k[*].l[*].m[*].n[*].o[*].p[*].q[*].r[*].s[*].t[*].u[*].v[*].w[*].x[*].y[*].z[*]",
"bench": "parse"
},
{
"comment": "filter projection",
"expression": "foo[?bar > baz][?qux > baz]",
"bench": "parse"
}
]
}
]
Loading
Loading