diff --git a/schemars/src/json_schema_impls/core.rs b/schemars/src/json_schema_impls/core.rs index 1734ddb..8c54892 100644 --- a/schemars/src/json_schema_impls/core.rs +++ b/schemars/src/json_schema_impls/core.rs @@ -73,6 +73,37 @@ fn with_null_type(mut obj: SchemaObject) -> SchemaObject { obj } +impl JsonSchema for Result { + no_ref_schema!(); + + fn schema_name() -> String { + format!("Result_Of_{}_Or_{}", T::schema_name(), E::schema_name()) + } + + fn json_schema(gen: &mut SchemaGenerator) -> Schema { + let mut ok_schema = SchemaObject::default(); + ok_schema.instance_type = Some(InstanceType::Object.into()); + ok_schema.object().required.insert("Ok".to_owned()); + ok_schema + .object() + .properties + .insert("Ok".to_owned(), gen.subschema_for::()); + + let mut err_schema = SchemaObject::default(); + err_schema.instance_type = Some(InstanceType::Object.into()); + err_schema.object().required.insert("Err".to_owned()); + err_schema + .object() + .properties + .insert("Err".to_owned(), gen.subschema_for::()); + + let mut schema = SchemaObject::default(); + schema.instance_type = Some(InstanceType::Object.into()); + schema.subschemas().any_of = Some(vec![ok_schema.into(), err_schema.into()]); + schema.into() + } +} + impl JsonSchema for std::marker::PhantomData { no_ref_schema!(); @@ -134,4 +165,21 @@ mod tests { assert_eq!(schema.extensions.get("nullable"), Some(&json!(true))); assert_eq!(schema.subschemas.is_none(), true); } + + #[test] + fn schema_for_result() { + let schema = schema_object_for::>(); + let any_of = schema.subschemas.unwrap().any_of.unwrap(); + assert_eq!(any_of.len(), 2); + + let ok_schema: SchemaObject = any_of[0].clone().into(); + let obj = ok_schema.object.unwrap(); + assert!(obj.required.contains("Ok")); + assert_eq!(obj.properties["Ok"], schema_for::()); + + let err_schema: SchemaObject = any_of[1].clone().into(); + let obj = err_schema.object.unwrap(); + assert!(obj.required.contains("Err")); + assert_eq!(obj.properties["Err"], schema_for::()); + } } diff --git a/schemars/src/json_schema_impls/mod.rs b/schemars/src/json_schema_impls/mod.rs index 286a9ed..0fc6f9b 100644 --- a/schemars/src/json_schema_impls/mod.rs +++ b/schemars/src/json_schema_impls/mod.rs @@ -16,11 +16,3 @@ mod primitives; mod sequences; mod serdejson; mod tuple; - -// TODO serde yaml value/map under feature flag -// https://github.com/serde-rs/serde/blob/ce75418e40a593fc5c0902cbf4a45305a4178dd7/serde/src/ser/impls.rs -// Result?, Duration, SystemTime, -// IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV6, SocketAddrV6, -// Path, PathBuf, OsStr, OsString, Wrapping, Reverse, AtomicBool, AtomicI8 etc., -// NonZeroU8 etc., ArcWeak, RcWeak, (!)?, Bound?, Range?, RangeInclusive?, -// CString?, CStr?, fmt::Arguments? diff --git a/schemars/tests/expected/result.json b/schemars/tests/expected/result.json new file mode 100644 index 0000000..156f500 --- /dev/null +++ b/schemars/tests/expected/result.json @@ -0,0 +1,46 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "title": "Result_Of_MyStruct_Or_Array_Of_String", + "type": "object", + "anyOf": [ + { + "type": "object", + "required": [ + "Ok" + ], + "properties": { + "Ok": { + "$ref": "#/definitions/MyStruct" + } + } + }, + { + "type": "object", + "required": [ + "Err" + ], + "properties": { + "Err": { + "type": "array", + "items": { + "type": "string" + } + } + } + } + ], + "definitions": { + "MyStruct": { + "type": "object", + "required": [ + "foo" + ], + "properties": { + "foo": { + "type": "integer", + "format": "int32" + } + } + } + } +} \ No newline at end of file diff --git a/schemars/tests/result.rs b/schemars/tests/result.rs new file mode 100644 index 0000000..e1030cf --- /dev/null +++ b/schemars/tests/result.rs @@ -0,0 +1,13 @@ +mod util; +use schemars::JsonSchema; +use util::*; + +#[derive(Debug, JsonSchema)] +struct MyStruct { + foo: i32, +} + +#[test] +fn result() -> TestResult { + test_default_generated_schema::>>("result") +}