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
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,20 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.3.0] - 2025-12-17

### Added

- **`query_value_result!` macro** for Result-returning queries ([#56](https://github.com/jiftechnify/valq/pull/56))
- A new flavor of `query_value!` that returns a `valq::Result` instead of an `Option`
- Enables better error handling for queries where keys or indices might not exist
- Supports all the same query syntax as `query_value!`

- **`transpose_tuple!` helper macro** for transposing tuples of Results/Options ([#58](https://github.com/jiftechnify/valq/pull/58))
- Convert `(Option<A>, Option<B>, ...)` into `Option<(A, B, ...)>`
- Convert `(Result<A>, Result<B>, ...)` into `Result<(A, B, ...)>`
- Particularly useful when combining multiple `query_value!`/`query_value_result!` calls

## [0.2.0] - 2025-12-12

### Added
Expand Down Expand Up @@ -48,5 +62,6 @@ Initial release with basic query functionality.
- Mutable reference extraction with `mut` prefix
- Basic type casting using `as_***()` methods with `->` operator

[0.3.0]: https://github.com/jiftechnify/valq/compare/0.2.0...0.3.0
[0.2.0]: https://github.com/jiftechnify/valq/compare/0.1.0...0.2.0
[0.1.0]: https://github.com/jiftechnify/valq/releases/tag/0.1.0
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "valq"
version = "0.2.0"
version = "0.3.0"
authors = ["jiftechnify <jiftech.stlfy@gmail.com>"]
edition = "2021"
license = "MIT"
Expand Down
42 changes: 35 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
[crates.io shield]: https://img.shields.io/crates/v/valq
[crates.io link]: https://crates.io/crates/valq

`valq` provides a macro for querying semi-structured ("JSON-ish") data **with the JavaScript-like syntax**.
`valq` provides macros for querying semi-structured ("JSON-ish") data **with the JavaScript-like syntax**.

Look & Feel:

Expand Down Expand Up @@ -34,13 +34,15 @@ Add this to the `Cargo.toml` in your project:
valq = "*"
```

## What's provided

The principal macro provided by this crate is `query_value!`.
Also, there is a `Result`-returning variant of `query_value!`, called `query_value_result!`.

## `query_value!` macro
### `query_value!` macro
A macro for querying, extracting and converting inner value of semi-structured data.

### Basic Queries
#### Basic Queries
```rust
// get field `foo` from JSON object `obj`
let foo = query_value!(obj.foo);
Expand All @@ -52,7 +54,7 @@ let head = query_value!(obj.arr[0]);
let abyss = query_value!(obj.path.to.matrix[0][1].abyss);
```

### Extracting Mutable Reference to Inner Value
#### Extracting Mutable Reference to Inner Value
```rust
use serde_json::{json, Value}

Expand All @@ -67,7 +69,7 @@ assert_eq!(query_value!(obj.foo.bar.x -> u64), Some(100));
assert_eq!(query_value!(obj.foo.bar.y -> u64), Some(200));
```

### Casting & Deserializing to Specified Type
#### Casting & Deserializing to Specified Type
```rust
// try to cast the queried value into `u64` using `as_u64()` method on that value.
// results in `None` in case of type mismatch
Expand All @@ -94,7 +96,7 @@ let j = json!({"author": {"name": "jiftechnify", "age": 31}});
let author: Option<Person> = query_value!(j.author >> (Person));
```

### Unwrapping Query Results with Default Values
#### Unwrapping Query Results with Default Values
```rust
use serde_json::json;
use valq::query_value;
Expand All @@ -105,7 +107,7 @@ assert_eq!(query_value!(obj.foo.bar -> u64 ?? 42), 42); // explicitly provided d
assert_eq!(query_value!(obj.foo.bar -> u64 ?? default), 0u64); // using u64::default()
```

## `query_value_result!` macro
### `query_value_result!` macro
A variant of `query_value!` that returns `Result<T, valq::Error>` instead of `Option<T>`.

```rust
Expand All @@ -128,6 +130,32 @@ let result = query_value_result!(obj.foo >> (Vec<u8>));
assert!(matches!(result, Err(Error::DeserializationFailed(_))));
```

### Helper: `transpose_tuple!` macro
Transposes a tuple of `Option`s/`Result`s into an `Option`/`Result` of a tuple.
This is meant to be used with `query_value!`/`query_value_result!` macros, for "cherry-picking" deep value from data.

```rust
use serde_json::json;
use valq::{query_value, transpose_tuple};

let data = json!({"name": "valq", "version": "0.2.0"});

// Combine multiple Option results into Option<tuple>
let picks = transpose_tuple!(
query_value!(data.name -> str),
query_value!(data.version -> str),
);
assert_eq!(picks, Some(("valq", "0.2.0")));

// For Result variant, "Result;" prefix is needed
let picks = transpose_tuple!(
Result;
query_value_result!(data.name -> str),
query_value_result!(data.version -> str),
);
assert!(picks.is_ok());
```

## Compatibility
The `query_value!` macro can be used with arbitrary data structure(to call, `Value`) that supports `get(&self, idx) -> Option<&Value>` method that retrieves a value at `idx`.

Expand Down