1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
//! Infers JSON Type Definition schemas from example inputs. //! //! JSON Type Definition, aka [RFC 8927](https://tools.ietf.org/html/rfc8927), //! is an easy-to-learn, standardized way to define a schema for JSON data. You //! can use JSON Typedef to portably validate data across programming languages, //! create dummy data, generate code, and more. //! //! This Rust crate can generate a JSON Typedef schema from example data. If you //! are looking to use this package as a CLI tool, see [this crate's //! README](https://github.com/jsontypedef/json-typedef-infer). The remainder of //! these docs are focused on this crate as a Rust library, and so focuses on //! the Rust API for using `jtd_fuzz`. //! //! # Quick start //! //! Here's how you can use this crate to infer a schema: //! //! ``` //! use serde_json::json; //! use jtd_infer::{Inferrer, Hints, HintSet, NumType}; //! //! let mut inferrer = Inferrer::new(Hints::new( //! NumType::Uint8, //! HintSet::new(vec![]), //! HintSet::new(vec![]), //! HintSet::new(vec![]), //! )); //! //! inferrer = inferrer.infer(json!({ "foo": true, "bar": "xxx" })); //! inferrer = inferrer.infer(json!({ "foo": false, "bar": null, "baz": 5 })); //! //! let inference = inferrer.into_schema(); //! //! assert_eq!( //! json!({ //! "properties": { //! "foo": { "type": "boolean" }, //! "bar": { "type": "string", "nullable": true }, //! }, //! "optionalProperties": { //! "baz": { "type": "uint8" }, //! }, //! }), //! serde_json::to_value(inference.into_serde_schema()).unwrap(), //! ) //! ``` mod hints; mod inferred_number; mod inferred_schema; pub use crate::hints::{HintSet, Hints}; pub use crate::inferred_number::NumType; use crate::inferred_schema::InferredSchema; use jtd::Schema; use serde_json::Value; /// Keeps track of a sequence of example inputs, and can be converted into an /// inferred schema. pub struct Inferrer<'a> { inference: InferredSchema, hints: Hints<'a>, } impl<'a> Inferrer<'a> { /// Constructs a new inferrer with a given set of hints. /// /// See the documentation for [`Hints`] for details on what affect they have /// on [`Inferrer::infer`]. pub fn new(hints: Hints<'a>) -> Self { Self { inference: InferredSchema::Unknown, hints, } } /// "Updates" the inference given an example data. /// /// Note that though the previous sentence uses the word "update", in Rust /// ownership terms this method *moves* `self`. pub fn infer(self, value: Value) -> Self { Self { inference: self.inference.infer(value, &self.hints), hints: self.hints, } } /// Converts the inference to a JSON Type Definition schema. /// /// It is guaranteed that the resulting schema will accept all of the inputs /// previously provided via [`Inferrer::infer`]. pub fn into_schema(self) -> Schema { self.inference.into_schema(&self.hints) } }