JMESPath.cr

A fully compliant Crystal implementation of JMESPath, a query language for JSON. JMESPath allows you to declaratively extract elements from complex JSON documents.

Installation

  1. Add the dependency to your shard.yml:

    dependencies:
      jmespath:
        github: qequ/jmespath.cr
  2. Run shards install

Usage

require "jmespath"

# Basic object access
data = %({"foo": {"bar": "baz"}})
JMESPath.search("foo.bar", data) # => "baz"

# Array operations
data = %({"people": [{"name": "bob"}, {"name": "alice"}]})
JMESPath.search("people[1].name", data) # => "alice"

# List projections
data = %({"people": [{"age": 20}, {"age": 25}, {"age": 30}]})
JMESPath.search("people[*].age", data) # => [20, 25, 30]

# Filters
data = %({"people": [
  {"name": "bob", "age": 20},
  {"name": "alice", "age": 25}
]})
JMESPath.search("people[?age > `20`].name", data) # => ["alice"]

# Multi-select hash
data = %({"foo": {"bar": "baz", "qux": "quux"}})
JMESPath.search("foo.{b: bar, q: qux}", data) # => {"b": "baz", "q": "quux"}

Built-in Functions

# String functions
JMESPath.search("length(foo)", %({"foo": "hello"}))           # => 5
JMESPath.search("starts_with(foo, 'hel')", %({"foo": "hello"})) # => true
JMESPath.search("join(', ', foo)", %({"foo": ["a", "b", "c"]})) # => "a, b, c"

# Array functions
JMESPath.search("sort(foo)", %({"foo": [3, 1, 2]}))     # => [1, 2, 3]
JMESPath.search("reverse(foo)", %({"foo": [1, 2, 3]}))  # => [3, 2, 1]
JMESPath.search("contains(foo, `2`)", %({"foo": [1, 2, 3]})) # => true

# Number functions
JMESPath.search("sum(foo)", %({"foo": [1, 2, 3]}))  # => 6
JMESPath.search("avg(foo)", %({"foo": [10, 20, 30]})) # => 20.0
JMESPath.search("abs(foo)", %({"foo": -5}))          # => 5

# Object functions
JMESPath.search("keys(foo)", %({"foo": {"a": 1, "b": 2}}))   # => ["a", "b"]
JMESPath.search("values(foo)", %({"foo": {"a": 1, "b": 2}})) # => [1, 2]

# Type conversion
JMESPath.search("to_string(foo)", %({"foo": 42}))    # => "42"
JMESPath.search("to_number(foo)", %({"foo": "42"}))   # => 42
JMESPath.search("type(foo)", %({"foo": "hello"}))     # => "string"

Expression References (expref)

The & operator creates a reference to an expression that is evaluated later by functions like sort_by, max_by, min_by, and map:

# Sort by a field
data = %({"people": [{"name": "bob", "age": 30}, {"name": "alice", "age": 25}]})
JMESPath.search("sort_by(people, &age)[*].name", data) # => ["alice", "bob"]

# Find max/min by expression
JMESPath.search("max_by(people, &age).name", data) # => "bob"
JMESPath.search("min_by(people, &age).name", data) # => "alice"

# Map an expression over an array
JMESPath.search("map(&name, people)", data) # => ["bob", "alice"]

Features

Full JMESPath specification support including:

TODO

Development

Contributions are welcome! Please feel free to submit a Pull Request.

Contributing

  1. Fork it (https://github.com/qequ/jmespath/fork)
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request

Contributors