A jq implementation in MoonBit
Dependencies
# Clone the repository
git clone https://github.com/moonbit-community/moobit-jq.git
cd moobit-jq
# Run tests to verify installation
moon test///|
/// Helper function: Evaluate a jq query and return newline-separated results.
/// This mimics the command-line jq tool's behavior.
fn jq(query : String, input : String) -> String raise {
let expr = @parser.parse(query)
let json = @json.parse(input)
@ast.eval(expr, json).collect().map(fn(v) { @debug.to_string(v) }).join("\n")
}moon run cmd/jq --target native -- -c '.foo' data.json
cat data.json | moon run cmd/jq --target native -- -r '.name'
moon run cmd/jq --target native -- -n -c '{ok: true}'
moon run cmd/jq --target native -- -f filter.jq data.jsonmoon build --target native --release cmd/jq
_build/native/release/build/cmd/jq/jq.exe -c '.items[]' data.json
**Explanation**: The `select(.age >= 18)` filters users 18 or older, then `{name: .name, email: .email}` constructs new objects with only those fields.
### 2. Optional Access with Defaults
Handle missing fields gracefully using `?` and `//`:
```mbt check
inspect(
jq(query, input),
content=(
#|String("(unknown)")
),
)
}
**Explanation**: `map(. * 2)` doubles each number, then `add` sums them all: `(1*2 + 2*2 + 3*2) = 12`.
### 4. Filter Logs by Level
Extract specific log messages based on severity:
```mbt check
///|
test "readme: extract error messages" {
///|
inspect(
jq(query, input),
content=(
#|String("disk full")
#|String("timeout")
),
)
}///|
test "readme: array slicing" {
let query = ".items[1:3] | reverse"
let input =
#|{ "items": [10, 20, 30, 40, 50] }
inspect(
jq(query, input),
content=(
#|Array([Number(30), Number(20)])
),
)
}///|
test "readme: recursive descent" {
let query = ".. | select(type == \"number\")"
let input =
#|{
#| "a": 1,
#| "b": { "c": 2, "d": { "e": 3 } }
#|}
inspect(
jq(query, input),
content=(
#|Number(1)
#|Number(2)
#|Number(3)
),
)
}moobit-jq/
├── moon.mod # Module metadata
├── README.mbt.md # This file (executable documentation)
├── TUTORIAL.md # CLI tutorial
├── ast/ # AST + streaming evaluator + integration tests
├── cmd/jq/ # Native jq-compatible CLI
├── parser/ # Parser (includes lexer)
├── tests/cram/ # Moon Cram CLI tests# Run all tests (415+ tests)
moon test
# Run specific package tests
moon test -p parser
moon test -p ast
# Type-check without running tests
moon check
# Type-check this README
moon check README.mbt.md
# Update test snapshots
moon test --updatemoon cram test tests/cram TUTORIAL.md# Format code
moon fmt
# Generate package interfaces
moon info
# Check for warnings
moon check --target all| Type | Description |
|---|---|
| Query | A compiled jq query that can be evaluated multiple times |
| Function | Signature | Description |
|---|---|---|
| parse | (String) -> Query raise | Compile a jq query string into a reusable Query |
| eval | (Query, Json) -> Iter[Json] raise | Evaluate a query, streaming results lazily |
| eval_all | (Query, Json) -> Array[Json] raise | Evaluate a query, collecting all results |
| run | (String, String) -> Array[Json] raise | Parse and evaluate in one step |
| run_json | (Query, Json) -> Array[Json] raise | Evaluate against already-parsed JSON |
| Method | Signature | Description |
|---|---|---|
| Query::eval | (Query, Json) -> Iter[Json] raise | Stream evaluation results |
| Query::eval_all | (Query, Json) -> Array[Json] raise | Collect all results |
| Query::eval_logs | (Query, String) -> Iter[Json] raise | Process NDJSON logs |
A jq implementation in MoonBit
Dependencies