A minimal, security-focused Ruby gem that wraps the jq C library for JSON transformation.
Add this line to your application's Gemfile:
gem 'jq'And then execute:
bundle installOr install it yourself:
gem install jqNote: This gem bundles jq 1.8.1 and builds it from source automatically during installation. No system dependencies are required.
require 'jq'
# Basic filter
result = JQ.filter('{"name":"Alice","age":30}', '.name')
# => "\"Alice\""
# Identity filter (compact output is the default)
result = JQ.filter('{"a":1}', '.')
# => "{\"a\":1}"
# Nested access
result = JQ.filter('{"user":{"name":"Bob"}}', '.user.name')
# => "\"Bob\""
# Array operations
result = JQ.filter('[1,2,3]', '.[1]')
# => "2"Get raw strings without JSON encoding (equivalent to jq -r):
result = JQ.filter('{"name":"Alice"}', '.name', raw_output: true)
# => "Alice" (not "\"Alice\"")Compact output is the default. JSON is returned on a single line without extra whitespace:
result = JQ.filter('{"a":1,"b":2}', '.')
# => "{\"a\":1,\"b\":2}" (default)
# To get pretty-printed output, set compact_output: false
result = JQ.filter('{"a":1,"b":2}', '.', compact_output: false)
# => "{\n \"a\": 1,\n \"b\": 2\n}"Sort object keys for deterministic output (equivalent to jq -S):
result = JQ.filter('{"z":1,"a":2}', '.', sort_keys: true)
# => "{\"a\":2,\"z\":1}"Return an array of all results instead of just the first:
result = JQ.filter('[1,2,3]', '.[]', multiple_outputs: true)
# => ["1", "2", "3"]
# Combining with raw_output
result = JQ.filter('["a","b","c"]', '.[]', multiple_outputs: true, raw_output: true)
# => ["a", "b", "c"]# Map operation
json = '[{"name":"Alice","age":30},{"name":"Bob","age":25}]'
result = JQ.filter(json, '[.[] | .name]')
# => "[\"Alice\",\"Bob\"]"
# Select operation
result = JQ.filter(json, '[.[] | select(.age > 26)]')
# => "[{\"name\":\"Alice\",\"age\":30}]"
# Multiple transformations
result = JQ.filter('{"a":1,"b":2,"c":3}', 'to_entries | map(.value) | add')
# => "6"Validate a filter before using it:
JQ.validate_filter!('.name')
# => true
JQ.validate_filter!('...invalid')
# raises JQ::CompileErrorThe gem defines four exception classes:
begin
JQ.filter('invalid json', '.')
rescue JQ::ParseError => e
puts "Invalid JSON: #{e.message}"
end
begin
JQ.filter('{}', '...invalid filter')
rescue JQ::CompileError => e
puts "Invalid filter: #{e.message}"
end
begin
JQ.filter('{}', '.nonexistent.deeply.nested')
rescue JQ::RuntimeError => e
puts "Runtime error: #{e.message}"
endException hierarchy:
JQ::Error- Base class for all jq-related errorsJQ::ParseError- Invalid JSON inputJQ::CompileError- Invalid jq filterJQ::RuntimeError- Runtime execution error
Status: Likely safe with jq 1.7+, but not officially guaranteed
This gem creates an isolated jq_state for each call, and jq 1.7+ fixed a critical thread-safety bug (PR #2546). Multi-threaded use is probably safe in MRI Ruby where the GVL serializes execution, but jq hasn't made formal thread-safety guarantees.
Recommendations:
- ✅ Use with jq 1.7+ (check:
jq --version) - ✅ MRI Ruby (standard Ruby) - likely safe due to GVL
⚠️ JRuby/TruffleRuby - use with caution (true parallel threads)- 🛡️ Safest for heavy parallel workloads: separate processes
See SECURITY.md for detailed thread safety information.
- The gem uses proper jv lifecycle management to prevent memory leaks
- Very large JSON documents (>100MB) may cause high memory usage
- Deeply nested structures may hit stack limits
- Complex filters may be slow - there is no timeout mechanism in v1.0
See SECURITY.md for detailed security information.
Key points:
- JSON input is parsed by jq's parser (no eval/injection risk)
- Filter expressions cannot execute system commands (safe by design)
- All inputs are validated for type before processing
- The extension uses proper memory management to prevent buffer overflows
After checking out the repo, run:
bundle install
bundle exec rake compile
bundle exec rake specTo check for memory leaks:
bundle exec rake compile CFLAGS="-fsanitize=address -g"
bundle exec rspec spec/memory_spec.rbBug reports and pull requests are welcome on GitHub at https://github.com/persona-id/jq-ruby.
The gem is available as open source under the terms of the MIT License.
jq itself is licensed under the MIT License. See https://github.com/jqlang/jq for details.