Don't include number format in schema for value

Guessing the format for serde_json::Number can be very misleading, so let's not
This commit is contained in:
Graham Esau 2021-03-25 19:47:36 +00:00
parent 9b71b428cb
commit 04996efeb3
6 changed files with 109 additions and 42 deletions

View file

@ -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<Self::Ok, Self::Error> {
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::<String>())
Ok(self.gen.subschema_for::<&str>())
}
fn collect_map<K, V, I>(self, iter: I) -> Result<Self::Ok, Self::Error>
@ -111,6 +124,10 @@ impl<'a> serde::Serializer for Serializer<'a> {
Ok(self.gen.subschema_for::<Option<Value>>())
}
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
self.serialize_none()
}
fn serialize_some<T: ?Sized>(mut self, value: &T) -> Result<Self::Ok, Self::Error>
where
T: serde::Serialize,
@ -166,12 +183,8 @@ impl<'a> serde::Serializer for Serializer<'a> {
Ok(schema)
}
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
Ok(self.gen.subschema_for::<()>())
}
fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
self.serialize_unit()
Ok(self.gen.subschema_for::<()>())
}
fn serialize_unit_variant(

View file

@ -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"
}
}
}

View file

@ -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,

View file

@ -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,

View file

@ -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,

View file

@ -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")
}