Crate magnet_schema
source ·Expand description
Magnet, a JSON/BSON schema generator
These two related crates, magnet_schema
and magnet_derive
define
a trait, BsonSchema
, and a proc-macro derive for the same trait,
which allows types to easily implement JSON schema validation for
use with MongoDB.
The trait defines a single function, bson_schema()
, that returns
a BSON Document
describing the validation schema of the type based
on its fields (for struct
s and tuples), variants (for enum
s), or
elements/entries (for array- and map-like types).
The types are expected to be serialized and deserialized using Serde,
and generally Magnet will try very hard to respect #[serde(...)]
annotations as faithfully as possible, but no Serialize + Deserialize
trait bounds are enforced on the types as this is not strictly necessary.
Usage Example
#[macro_use]
extern crate serde_derive;
extern crate serde;
#[macro_use]
extern crate bson;
#[macro_use]
extern crate magnet_derive;
extern crate magnet_schema;
use std::collections::HashSet;
use magnet_schema::BsonSchema;
#[derive(BsonSchema)]
struct Person {
name: String,
nicknames: HashSet<String>,
age: usize,
contact: Option<Contact>,
}
#[derive(BsonSchema, Serialize, Deserialize)]
#[serde(tag = "type", content = "value")]
enum Contact {
Email(String),
Phone(u64),
}
fn main() {
println!("{:#?}", Person::bson_schema());
}
Custom Attributes
-
#[serde(rename = "new_name")]
: Magnet will respect Serde’s field/variant renaming attribute by default. -
#[serde(rename_all = "rename_rule")]
: it will also respect Serde’srename_all
rule. -
#[magnet(min_incl = "-1337")]
— enforces an inclusive minimum for fields of numeric types -
#[magnet(min_excl = "42")]
— enforces an exclusive “minimum” (infimum) for fields of numeric types -
#[magnet(max_incl = "63")]
— enforces an inclusive maximum for fields of numeric types -
#[magnet(max_excl = "64")]
— enforces an exclusive “maximum” (supremum) for fields of numeric types
Development Roadmap
-
[x]
DefineBsonSchema
trait -
[x]
impl BsonSchema
for most primitives/std::
types -
[x]
Cargofeature
s for implementingBsonSchema
for “atomic” types in foreign crates, for instance,url::Url
anduuid::Uuid
. -
[x]
#[derive(BsonSchema)]
on regular, named-field structs -
[x]
#[derive(BsonSchema)]
on newtype structs -
[x]
#[derive(BsonSchema)]
on tuple structs -
[x]
#[derive(BsonSchema)]
on unit structs -
[ ]
#[derive(BsonSchema)]
on enums-
[x]
unit variants -
[ ]
newtype variants-
[x]
newtype variants around structs and maps -
[ ]
newtype variants around inner, transitiveenum
s
-
-
[x]
tuple variants -
[x]
struct variants -
[x]
respect Serde tagging conventions: external/internal/adjacent
-
-
[x]
Respect more#[serde(...)]
attributes, for example:rename
,rename_all
-
[ ]
Respect more#[serde(...)]
attributes, for example:default
,skip
,skip_serializing
,skip_deserializing
-
[x]
Handle generic types in proc-macro derive -
[ ]
Standard (non-MongoDB-specific) JSON schema support (approach?) -
[x]
unit tests -
[x]
documentation for attributes -
[ ]
impl BsonSchema
for more esoteric primitives/standard types such as specialization of[u8]
/Vec<u8>
as binary, adding a validation regex"pattern"
toPath
andPathBuf
, etc. -
[ ]
Add our own attributes-
[x]
magnet(rename = "...")
— renames the field or variant to the name specified as the value of therename
attribute -
[ ]
magnet(regex = "foo?|[ba]r{3,6}")
— custom validation; implies"type": "string"
. Patterns are implicitly enclosed between^...$
for robustness. -
[ ]
magnet(unsafe_regex = "^nasty-regex$")
— just likemagnet(regex)
, but no automatic enclosing in^...$
happens. This may allow invalid data to pass validation!!! -
[ ]
magnet(non_empty)
— for collections: same asmin_length = "1"
. -
[ ]
magnet(min_length = "16")
— for collections/tuples etc. -
[ ]
magnet(max_length = "32")
— for collections/tuples etc. -
[x]
magnet(min_incl = "-1337")
— inclusive minimum for numbers -
[x]
magnet(min_excl = "42")
— exclusive “minimum” (infimum) for numbers -
[x]
magnet(max_incl = "63")
— inclusive maximum for numbers -
[x]
magnet(max_excl = "64")
— exclusive “maximum” (supremum) for numbers -
[ ]
magnet(allow_extra_fields)
— sets"additionalProperties": true
. By default, Magnet sets this field tofalse
for maximal safety. Allowing arbitrary data to be inserted in a DB is generally a Bad Idea, as it may lead to code injection (MongoDB
supports storing JavaScript in a collection! Madness!) or at best, denial-of-service (DoS) attacks. -
[ ]
magnet(allow_extra_fields = "ExtraFieldType")
— sets"additionalProperties": ExtraFieldType::bson_schema()
, so that unlisted additional object fields are allowed provided that they conform to the schema of the specified type.
-