diff --git a/schemars/src/ser.rs b/schemars/src/ser.rs index f70ae3e..fc2bba0 100644 --- a/schemars/src/ser.rs +++ b/schemars/src/ser.rs @@ -35,6 +35,18 @@ macro_rules! forward_to_subschema_for { }; } +macro_rules! return_instance_type { + ($fn:ident, $ty:ty, $instance_type:ident) => { + fn $fn(self, _value: $ty) -> Result { + Ok(SchemaObject { + instance_type: Some(InstanceType::$instance_type.into()), + ..Default::default() + } + .into()) + } + }; +} + impl<'a> serde::Serializer for Serializer<'a> { type Ok = Schema; type Error = Error; @@ -47,19 +59,20 @@ impl<'a> serde::Serializer for Serializer<'a> { type SerializeStruct = SerializeMap<'a>; type SerializeStructVariant = Self; + return_instance_type!(serialize_i8, i8, Integer); + return_instance_type!(serialize_i16, i16, Integer); + return_instance_type!(serialize_i32, i32, Integer); + return_instance_type!(serialize_i64, i64, Integer); + return_instance_type!(serialize_i128, i128, Integer); + return_instance_type!(serialize_u8, u8, Integer); + return_instance_type!(serialize_u16, u16, Integer); + return_instance_type!(serialize_u32, u32, Integer); + return_instance_type!(serialize_u64, u64, Integer); + return_instance_type!(serialize_u128, u128, Integer); + return_instance_type!(serialize_f32, f32, Number); + return_instance_type!(serialize_f64, f64, Number); + forward_to_subschema_for!(serialize_bool, bool); - forward_to_subschema_for!(serialize_i8, i8); - forward_to_subschema_for!(serialize_i16, i16); - forward_to_subschema_for!(serialize_i32, i32); - forward_to_subschema_for!(serialize_i64, i64); - forward_to_subschema_for!(serialize_i128, i128); - forward_to_subschema_for!(serialize_u8, u8); - forward_to_subschema_for!(serialize_u16, u16); - forward_to_subschema_for!(serialize_u32, u32); - forward_to_subschema_for!(serialize_u64, u64); - forward_to_subschema_for!(serialize_u128, u128); - forward_to_subschema_for!(serialize_f32, f32); - forward_to_subschema_for!(serialize_f64, f64); forward_to_subschema_for!(serialize_char, char); forward_to_subschema_for!(serialize_str, &str); forward_to_subschema_for!(serialize_bytes, &[u8]); @@ -68,7 +81,7 @@ impl<'a> serde::Serializer for Serializer<'a> { where T: Display, { - Ok(self.gen.subschema_for::()) + Ok(self.gen.subschema_for::<&str>()) } fn collect_map(self, iter: I) -> Result @@ -111,6 +124,10 @@ impl<'a> serde::Serializer for Serializer<'a> { Ok(self.gen.subschema_for::>()) } + fn serialize_unit(self) -> Result { + self.serialize_none() + } + fn serialize_some(mut self, value: &T) -> Result where T: serde::Serialize, @@ -166,12 +183,8 @@ impl<'a> serde::Serializer for Serializer<'a> { Ok(schema) } - fn serialize_unit(self) -> Result { - Ok(self.gen.subschema_for::<()>()) - } - fn serialize_unit_struct(self, _name: &'static str) -> Result { - self.serialize_unit() + Ok(self.gen.subschema_for::<()>()) } fn serialize_unit_variant( diff --git a/schemars/tests/expected/from_json_value.json b/schemars/tests/expected/from_json_value.json new file mode 100644 index 0000000..0d94b66 --- /dev/null +++ b/schemars/tests/expected/from_json_value.json @@ -0,0 +1,49 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "examples": [ + { + "bool": true, + "minusOne": -1, + "null": null, + "object": { + "array": [ + "foo", + "bar" + ] + }, + "one": 1, + "zero": 0, + "zeroPointZero": 0.0 + } + ], + "type": "object", + "properties": { + "bool": { + "type": "boolean" + }, + "minusOne": { + "type": "integer" + }, + "null": true, + "object": { + "type": "object", + "properties": { + "array": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "one": { + "type": "integer" + }, + "zero": { + "type": "integer" + }, + "zeroPointZero": { + "type": "number" + } + } +} \ No newline at end of file diff --git a/schemars/tests/expected/from_value_2019_09.json b/schemars/tests/expected/from_value_2019_09.json index 77e8953..9cea709 100644 --- a/schemars/tests/expected/from_value_2019_09.json +++ b/schemars/tests/expected/from_value_2019_09.json @@ -26,8 +26,7 @@ "type": "object", "properties": { "myInt": { - "type": "integer", - "format": "int32" + "type": "integer" }, "myBool": { "type": "boolean" @@ -39,8 +38,7 @@ "my_map": { "type": "object", "additionalProperties": { - "type": "number", - "format": "double" + "type": "number" } }, "my_vec": { @@ -66,9 +64,7 @@ "minLength": 1 }, { - "type": "integer", - "format": "uint8", - "minimum": 0.0 + "type": "integer" } ], "maxItems": 2, diff --git a/schemars/tests/expected/from_value_draft07.json b/schemars/tests/expected/from_value_draft07.json index 936eeaf..dec3996 100644 --- a/schemars/tests/expected/from_value_draft07.json +++ b/schemars/tests/expected/from_value_draft07.json @@ -26,8 +26,7 @@ "type": "object", "properties": { "myInt": { - "type": "integer", - "format": "int32" + "type": "integer" }, "myBool": { "type": "boolean" @@ -39,8 +38,7 @@ "my_map": { "type": "object", "additionalProperties": { - "type": "number", - "format": "double" + "type": "number" } }, "my_vec": { @@ -66,9 +64,7 @@ "minLength": 1 }, { - "type": "integer", - "format": "uint8", - "minimum": 0.0 + "type": "integer" } ], "maxItems": 2, diff --git a/schemars/tests/expected/from_value_openapi3.json b/schemars/tests/expected/from_value_openapi3.json index 52514e2..132a59a 100644 --- a/schemars/tests/expected/from_value_openapi3.json +++ b/schemars/tests/expected/from_value_openapi3.json @@ -4,8 +4,7 @@ "type": "object", "properties": { "myInt": { - "type": "integer", - "format": "int32" + "type": "integer" }, "myBool": { "type": "boolean" @@ -19,8 +18,7 @@ "my_map": { "type": "object", "additionalProperties": { - "type": "number", - "format": "double" + "type": "number" } }, "my_vec": { @@ -46,9 +44,7 @@ "minLength": 1 }, { - "type": "integer", - "format": "uint8", - "minimum": 0.0 + "type": "integer" } ], "maxItems": 2, diff --git a/schemars/tests/from_value.rs b/schemars/tests/from_value.rs index 9e6943f..3009933 100644 --- a/schemars/tests/from_value.rs +++ b/schemars/tests/from_value.rs @@ -1,8 +1,7 @@ mod util; -use std::collections::HashMap; - -use schemars::gen::SchemaSettings; +use schemars::gen::{SchemaGenerator, SchemaSettings}; use serde::Serialize; +use std::collections::HashMap; use util::*; #[derive(Serialize)] @@ -75,3 +74,21 @@ fn schema_from_value_matches_openapi3() -> TestResult { test_schema(&actual, "from_value_openapi3") } + +#[test] +fn schema_from_json_value() -> TestResult { + let gen = SchemaGenerator::default(); + let actual = gen.into_root_schema_for_value(&serde_json::json!({ + "zero": 0, + "one": 1, + "minusOne": -1, + "zeroPointZero": 0.0, + "bool": true, + "null": null, + "object": { + "array": ["foo", "bar"] + }, + }))?; + + test_schema(&actual, "from_json_value") +}