hana
Version, currently 0.1.12 versions
- 0.1.1latestFeb 14, 2026
- 0.1.0not indexedFeb 15, 2026
github.com/cyangle/hana.cr
An implementation of JSON Patch and JSON Pointer for Crystal
Installation
# Add this to your shard.yml
dependencies:
hana:
github: cyangle/hana.cr
version: ~> 0.1.1Then run:
shards installshard.yml
- Crystal
>= 1.13.2- License
- MIT
- Author
- Chao Yang
Dependencies
Development Dependencies
- ameba*github: crystal-ameba/amebadev
README
hana
Crystal port of the Ruby gem [hana]3.
Implementation of [JSON Patch]1 (RFC 6902) and [JSON Pointer]2 (RFC 6901).
Installation
-
Add the dependency to your
shard.yml:dependencies: hana: github: cyangle/hana.cr version: ~> 0.1.1 -
Run
shards install
Requirements: Crystal >= 1.13.2
Usage
JSON Patch
Apply patches to JSON documents. Supports all RFC 6902 operations: add, remove, replace, move, copy, and test.
require "hana"
doc = JSON.parse(%({
"name": "John",
"age": 30,
"tags": ["developer"]
}))
# Create patch from JSON string
patch = Hana::Patch.new(%([
{ "op": "replace", "path": "/name", "value": "Jane" },
{ "op": "add", "path": "/email", "value": "jane@example.com" },
{ "op": "remove", "path": "/age" },
{ "op": "add", "path": "/tags/-", "value": "designer" }
]))
result = patch.apply(doc)
puts result.to_json
# {"name":"Jane","tags":["developer","designer"],"email":"jane@example.com"}
Patch Operations
| Operation | Description | Example |
|---|---|---|
add | Add a value | {"op": "add", "path": "/foo", "value": "bar"} |
remove | Remove a value | {"op": "remove", "path": "/foo"} |
replace | Replace a value | {"op": "replace", "path": "/foo", "value": "baz"} |
move | Move a value | {"op": "move", "from": "/foo", "path": "/bar"} |
copy | Copy a value | {"op": "copy", "from": "/foo", "path": "/bar"} |
test | Test a value matches | {"op": "test", "path": "/foo", "value": "bar"} |
Creating Patches
# From JSON string
patch = Hana::Patch.new(%([{"op": "add", "path": "/foo", "value": "bar"}]))
# From IO
patch = Hana::Patch.new(File.open("patches.json"))
# From Array
ops = [{"op" => JSON::Any.new("add"), "path" => JSON::Any.new("/foo"), "value" => JSON::Any.new("bar")}]
patch = Hana::Patch.new(ops)
JSON Pointer
Evaluate JSON Pointers to extract values from JSON documents.
require "hana"
doc = JSON.parse(%({
"users": [
{"name": "Alice", "role": "admin"},
{"name": "Bob", "role": "user"}
],
"config": {
"debug": true
}
}))
# Get nested values
pointer = Hana::Pointer.new("/users/0/name")
puts pointer.eval(doc) # "Alice"
pointer = Hana::Pointer.new("/users/1/role")
puts pointer.eval(doc) # "user"
pointer = Hana::Pointer.new("/config/debug")
puts pointer.eval(doc) # true
Development
hana runs tests from json-patch/json-patch-tests. Fetch the git submodule by running:
git submodule init
git submodule update
Install dependencies with:
shards install
Then run the tests with:
crystal spec
Linting
Format code with Crystal's built-in formatter:
crystal tool format
Run static analysis with Ameba:
bin/ameba
Contributing
- Fork it (https://github.com/cyangle/hana.cr/fork)
- Create your feature branch (
git checkout -b my-new-feature) - Commit your changes (
git commit -am 'Add some feature') - Push to the branch (
git push origin my-new-feature) - Create a new Pull Request
Contributors
- Chao Yang - creator and maintainer
License
This project is licensed under the MIT License - see the LICENSE file for details.
Documentation
Built from the current release. The first visit to a release nobody has asked for starts its build.
Links
This release
- Version
0.1.1- Tagged
- Feb 14, 2026
- Commit
32ce89111c60- Crystal
>= 1.13.2- Indexed
- yes
Dependents
No indexed shard depends on this one yet.
Repository
github.com/cyangle/hana.cr
Metadata
- Created
- Aug 12, 2026
- Updated
- Aug 17, 2026
- Synced
- Aug 17, 2026
- Versions
- 2