googletest-json-serde

Crates.iogoogletest-json-serde
lib.rsgoogletest-json-serde
version0.5.0
created_at2025-09-29 06:06:17.635752+00
updated_at2026-01-07 19:53:36.059766+00
descriptionGoogleTest matchers for serde_json::Value
homepagehttps://github.com/chege/googletest-json-serde
repositoryhttps://github.com/chege/googletest-json-serde
max_upload_size
id1859029
size159,893
(chege)

documentation

README

Logo

Overview | Installation | Usage | Features | More Examples | Documentation | Contributing | License

A set of matcher macros for ergonomic JSON testing with googletest-rust.

These tiny, focused matchers make it effortless to assert on serde_json::Value in Rust tests.

Crates.io CI Docs.rs License

Overview

googletest-json-serde adds focused matcher macros for JSON so your Rust tests read like intent, not plumbing. It handles heterogeneous arrays, deep object patterns, path checks, and produces readable failure messages with path context.

Installation

Add as a dev-dependency:

cargo add googletest-json-serde --dev

Usage

use googletest::prelude::*;
use googletest_json_serde::json as j;
use serde_json::json;

let actual = json!({
    "vampire": { "name": "Nandor the Relentless", "age": 758, "familiar": "Guillermo" },
    "house": { "city": "Staten Island", "roommates": ["Laszlo", "Nadja", "Colin Robinson"] }
});

assert_that!(
    actual,
    j::pat!({
        "vampire": {
            "name": starts_with("Nandor"),
            "age": gt(500),
            "familiar": eq("Guillermo"),
        },
        "house": {
            "city": eq("Staten Island"),
            "roommates": j::unordered_elements_are![
                eq("Laszlo"),
                eq("Nadja"),
                contains_substring("Robinson"),
            ],
        },
        .. // allow extra fields
    })
);

Features

  • Object patterns:
    • j::matches_pattern! / j::pat! (strict or relaxed)
  • Arrays:
    • Ordered: j::elements_are!
    • Unordered: j::unordered_elements_are!
    • Contains-each: j::contains_each!
    • Contained-in: j::is_contained_in!
    • Length: j::len!
    • Apply to all elements: j::each!
    • Type guard: j::each_is_string()/number/boolean/null/array/object
  • Primitives and kinds:
    • j::primitive!, j::is_number/integer/fractional_number/whole_number/string/boolean, j::is_true/false, j::is_null, j::is_not_null, j::is_empty_string/non_empty_string, j::is_empty_array/object, j::is_non_empty_array/object
  • Paths and shape:
    • j::has_paths, j::has_only_paths, j::has_path_with!
  • Optional fields:
    • j::optional!
  • Clear diagnostics that point to the failing path or element.

More Examples

Primitives

use googletest::prelude::*;
use googletest_json_serde::json as j;
use serde_json::json;

assert_that!(json!(42),         j::primitive!(gt(40_i64)));
assert_that!(json!("Laszlo"),   j::primitive!(starts_with("Las")));
assert_that!(json!(true),       j::is_true());
assert_that!(json!(null),       j::is_null());
assert_that!(json!(7),          j::is_integer());
assert_that!(json!(7.0),        j::is_whole_number());
assert_that!(json!(7.25),       j::is_fractional_number());

Path value matching

use googletest::prelude::*;
use googletest_json_serde::json as j;
use serde_json::json;

let value = json!({"user": {"id": 7, "name": "Ada"}});
assert_that!(value, j::has_path_with!("user.name", "Ada"));
assert_that!(value, j::has_path_with!("user.id", json!(7)));
assert_that!(value, j::has_path_with!("user.name", starts_with("A")));

Predicates

use googletest::prelude::*;
use googletest_json_serde::json as j;
use serde_json::json;

assert_that!(json!(42), j::predicate(|v| v.as_i64().map_or(false, |n| n > 0)));
assert_that!(json!("Energy vampire"), j::predicate(|v| v.as_str().map_or(false, |s| s.contains("Energy"))));

Objects

use googletest::prelude::*;
use googletest_json_serde::json as j;
use serde_json::json;

assert_that!(
    json!({"name": "Laszlo", "age": 310, "familiar": null}),
    j::pat!({
        "name": starts_with("Las"),
        "age": gt(300),
        "familiar": j::is_null(),
        .. // allow extras like hobbies or cursed hats
    })
);

Arrays

use googletest::prelude::*;
use googletest_json_serde::json as j;
use serde_json::json;

assert_that!(
    json!(["Nandor", 758, true]),
    j::elements_are![eq("Nandor"), j::is_number(), is_true()]
);

assert_that!(
    json!(["Laszlo", "Nadja", "Colin Robinson"]),
    j::unordered_elements_are![eq("Colin Robinson"), "Laszlo", "Nadja"]
);

assert_that!(
    json!(["familiar", 1, null]),
    j::contains_each![j::is_string(), j::is_not_null()]
);

assert_that!(
    json!(["Nandor", "Nadja"]),
    j::each_is_string()
);

Combined Example

use googletest::prelude::*;
use googletest_json_serde::json as j;
use serde_json::json;

assert_that!(
    json!({
        "guests": [
            {"name": "Baron Afanas", "age": 2000},
            {"name": "The Guide", "age": 500}
        ],
        "house": { "city": "Staten Island", "roommates": 4 },
        "ignored": true
    }),
    j::pat!({
        "guests": j::unordered_elements_are![
            j::pat!({ "name": starts_with("Baron"), "age": gt(1500) }),
            j::pat!({ "name": eq("The Guide"), "age": ge(400) })
        ],
        "house": { "city": eq("Staten Island"), "roommates": eq(4) },
        ..
    })
);

Documentation

Contributing

License

Dual-licensed under MIT or Apache-2.0.

Commit count: 98

cargo fmt