11#![ allow( clippy:: large_enum_variant) ]
22use crate :: openapi:: * ;
33use schemars:: Schema ;
4- use serde:: { Deserialize , Serialize } ;
4+ use serde:: { ser:: SerializeMap , Deserialize , Serialize } ;
5+ use serde_json:: json;
56
6- #[ derive( Debug , Clone , Serialize , Deserialize , PartialEq , schemars:: JsonSchema ) ]
7+ #[ derive( Debug , Clone , Deserialize , PartialEq , schemars:: JsonSchema ) ]
78pub struct SchemaObject {
89 #[ serde( flatten) ]
910 pub json_schema : Schema ,
1011 /// Additional external documentation for this schema.
1112 #[ serde( rename = "externalDocs" ) ]
12- #[ serde( skip_serializing_if = "Option::is_none" ) ]
1313 pub external_docs : Option < ExternalDocumentation > ,
1414 /// A free-form property to include an example of an instance for this
1515 /// schema. To represent examples that cannot be naturally represented in
@@ -18,16 +18,52 @@ pub struct SchemaObject {
1818 /// been deprecated in favor of the JSON Schema `examples` keyword. Use
1919 /// of `example` is discouraged, and later versions of this
2020 /// specification may remove it.
21- #[ serde( skip_serializing_if = "Option::is_none" ) ]
2221 pub example : Option < serde_json:: Value > ,
2322}
2423
24+ impl Serialize for SchemaObject {
25+ fn serialize < S > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error >
26+ where
27+ S : serde:: Serializer ,
28+ {
29+ if self . external_docs . is_none ( ) && self . example . is_none ( ) {
30+ return self . json_schema . serialize ( serializer) ;
31+ }
32+
33+ let mut map = serializer. serialize_map ( None ) ?;
34+ match self . json_schema . as_bool ( ) {
35+ Some ( true ) => { }
36+ Some ( false ) => {
37+ map. serialize_entry ( "not" , & json ! ( { } ) ) ?;
38+ }
39+ _ => {
40+ let object = self
41+ . json_schema
42+ . as_object ( )
43+ . expect ( "JSON schema must be either a bool or an object" ) ;
44+ for ( k, v) in object {
45+ map. serialize_entry ( k, v) ?;
46+ }
47+ }
48+ }
49+
50+ if let Some ( value) = & self . external_docs {
51+ map. serialize_entry ( "externalDocs" , value) ?;
52+ }
53+ if let Some ( value) = & self . example {
54+ map. serialize_entry ( "example" , value) ?;
55+ }
56+
57+ map. end ( )
58+ }
59+ }
60+
2561#[ cfg( test) ]
2662mod tests {
2763 use crate :: openapi:: ExternalDocumentation ;
2864
2965 use super :: SchemaObject ;
30- use schemars:: Schema ;
66+ use schemars:: { json_schema , Schema } ;
3167 use serde_json:: json;
3268
3369 #[ test]
@@ -63,4 +99,58 @@ mod tests {
6399 } )
64100 ) ;
65101 }
102+
103+ #[ test]
104+ fn test_serialize_true_schema ( ) {
105+ let serialized = serde_json:: to_value ( SchemaObject {
106+ json_schema : json_schema ! ( true ) ,
107+ external_docs : None ,
108+ example : None ,
109+ } )
110+ . unwrap ( ) ;
111+
112+ assert_eq ! ( serialized, json!( true ) ) ;
113+ }
114+
115+ #[ test]
116+ fn test_serialize_true_schema_with_external_docs ( ) {
117+ let serialized = serde_json:: to_value ( SchemaObject {
118+ json_schema : json_schema ! ( true ) ,
119+ external_docs : Some ( ExternalDocumentation {
120+ description : None ,
121+ url : "http://example.org" . to_owned ( ) ,
122+ extensions : Default :: default ( ) ,
123+ } ) ,
124+ example : None ,
125+ } )
126+ . unwrap ( ) ;
127+
128+ assert_eq ! (
129+ serialized,
130+ json!( {
131+ "externalDocs" : { "url" : "http://example.org" } ,
132+ } )
133+ ) ;
134+ }
135+
136+ #[ test]
137+ fn test_serialize_false_schema_with_example ( ) {
138+ let example = json ! ( {
139+ "what a useless schema" : "even this example is wrong" ,
140+ } ) ;
141+ let serialized = serde_json:: to_value ( SchemaObject {
142+ json_schema : json_schema ! ( false ) ,
143+ external_docs : None ,
144+ example : Some ( example. clone ( ) ) ,
145+ } )
146+ . unwrap ( ) ;
147+
148+ assert_eq ! (
149+ serialized,
150+ json!( {
151+ "not" : { } ,
152+ "example" : example,
153+ } )
154+ ) ;
155+ }
66156}
0 commit comments