8 stable releases
2.2.3 | Sep 5, 2024 |
---|---|
2.2.2 | Aug 16, 2024 |
2.1.2 | Aug 16, 2024 |
2.1.1 | Jul 31, 2024 |
2.0.0 | Jul 31, 2024 |
#1748 in Encoding
467 downloads per month
11KB
124 lines
merde_json_types
Logo by MisiasArt
merde_json_types
is a companion crate to merde_json,
providing wrapper types that solve two problems at once.
Problem 1: Most crates have types that do not implement the merde_json
traits
I'm thinking about the time crate, the chrono crate, camino, etc.
If you have, say, a time::OffsetDateTime
in one of your structs,
then merde_json's derive macro will not work. You are going to need
a wrapper of some sort, and that's the kind of type this crate provides.
If you enable the time-serialize
, time-deserialize
, and merde_json
features, you can do this:
use merde_json::{from_str, JsonSerialize, ToRustValue};
use merde_json_types::time::Rfc3339;
let dt = Rfc3339(time::OffsetDateTime::now_utc());
let serialized = dt.to_json_string();
let deserialized: Rfc3339<time::OffsetDateTime> =
merde_json::from_str(&serialized).unwrap().to_rust_value().unwrap();
assert_eq!(dt, deserialized);
Problem 2: Keeping merde_json
optional
The time::Rfc3339 type is exported by this crate as soon as the time-types
feature is enabled. But merde_json_types
doesn't even depend on merde_json
(or provide serialization/deserialization implementations) unless you activate
its merde_json
feature!
That means, you can have your crate unconditionally depend on merde_json_types
,
and use Rfc3339
in your public structs:
use merde_json::{Fantome, JsonSerialize, ToRustValue};
use merde_json_types::time::Rfc3339;
#[derive(Debug, PartialEq, Eq)]
pub struct Person<'src, 'val> {
pub name: String,
pub birth_date: Rfc3339<time::OffsetDateTime>,
pub _boo: Fantome<'src, 'val>,
}
merde_json::derive! {
impl (JsonSerialize, JsonDeserialize) for Person { name, birth_date }
}
And still only depend on merde_json
when your own feature gets activated:
[dependencies]
merde_json_types = "2"
merde_json = { version = "2", optional = true }
[features]
merde_json = ["dep:merde_json", "merde_json_types/merde_json"]
Of course, for that to work, we need to get rid of any unconditional mention of
merde_json
in our code, which would become something like:
use std::marker::PhantomData;
use merde_json_types::time::Rfc3339;
#[derive(Debug, PartialEq, Eq)]
pub struct Person<'src, 'val> {
pub name: String,
pub birth_date: Rfc3339<time::OffsetDateTime>,
/// This field still _has_ to be named `_boo`, but we can't use
/// the `Fantome` type here without pulling in `merde_json`: so,
/// we use `PhantomData` instead.
pub _boo: PhantomData<(&'src (), &'val ())>,
}
#[cfg(feature = "merde_json")]
merde_json::derive! {
impl (JsonSerialize, JsonDeserialize) for Person { name, birth_date }
}
Dependencies
~0–0.8MB
~16K SLoC