1use crate::{ast::*, attr::WithAttr, idents::*};
2use proc_macro2::{Span, TokenStream};
3use quote::ToTokens;
4use serde_derive_internals::ast::Style;
5use serde_derive_internals::attr::{self as serde_attr, Default as SerdeDefault, TagType};
6use syn::spanned::Spanned;
7
8pub struct SchemaExpr {
9 definitions: Vec<TokenStream>,
11 creator: TokenStream,
13 mutators: Vec<TokenStream>,
15}
16
17impl From<TokenStream> for SchemaExpr {
18 fn from(creator: TokenStream) -> Self {
19 Self {
20 definitions: Vec::new(),
21 creator,
22 mutators: Vec::new(),
23 }
24 }
25}
26
27impl ToTokens for SchemaExpr {
28 fn to_tokens(&self, tokens: &mut TokenStream) {
29 let Self {
30 definitions,
31 creator,
32 mutators,
33 } = self;
34
35 tokens.extend(if mutators.is_empty() {
36 quote!({
37 #(#definitions)*
38 #creator
39 })
40 } else {
41 quote!({
42 #(#definitions)*
43 let mut #SCHEMA = #creator;
44 #(#mutators)*
45 #SCHEMA
46 })
47 });
48 }
49}
50
51pub fn expr_for_container(cont: &Container) -> SchemaExpr {
52 let type_from = cont
53 .serde_attrs
54 .type_from()
55 .or(cont.serde_attrs.type_try_from());
56 let type_into = cont.serde_attrs.type_into();
57
58 let mut schema_expr = if let Some(with) = &cont.attrs.with {
59 expr_for_container_with(cont, with)
60 } else if let Some(transparent_field) = cont.transparent_field() {
61 expr_for_newtype_struct(cont, transparent_field)
62 } else if let (Some(from), Some(into)) = (type_from, type_into) {
63 quote! {
64 if #GENERATOR.contract().is_deserialize() {
65 <#from as schemars::JsonSchema>::json_schema(#GENERATOR)
66 } else {
67 <#into as schemars::JsonSchema>::json_schema(#GENERATOR)
68 }
69 }
70 .into()
71 } else {
72 let schema_expr = match &cont.data {
73 Data::Struct(Style::Unit, _) => expr_for_unit_struct(),
74 Data::Struct(Style::Newtype, fields) => expr_for_newtype_struct(cont, &fields[0]),
75 Data::Struct(Style::Tuple, fields) => expr_for_tuple_struct(cont, fields),
76 Data::Struct(Style::Struct, fields) => expr_for_struct(
77 cont,
78 fields,
79 cont.serde_attrs.default(),
80 cont.serde_attrs.deny_unknown_fields(),
81 ),
82 Data::Enum(variants) => expr_for_enum(cont, variants, &cont.serde_attrs),
83 };
84
85 if let Some(from) = type_from {
86 quote! {
87 if #GENERATOR.contract().is_deserialize() {
88 <#from as schemars::JsonSchema>::json_schema(#GENERATOR)
89 } else {
90 #schema_expr
91 }
92 }
93 .into()
94 } else if let Some(into) = type_into {
95 quote! {
96 if #GENERATOR.contract().is_serialize() {
97 <#into as schemars::JsonSchema>::json_schema(#GENERATOR)
98 } else {
99 #schema_expr
100 }
101 }
102 .into()
103 } else {
104 schema_expr
105 }
106 };
107
108 cont.add_mutators(&mut schema_expr.mutators);
109
110 schema_expr
111}
112
113pub fn expr_for_repr(cont: &Container) -> Result<SchemaExpr, syn::Error> {
114 let repr_type = cont.attrs.repr.as_ref().ok_or_else(|| {
115 syn::Error::new(
116 Span::call_site(),
117 "JsonSchema_repr: missing #[repr(...)] attribute",
118 )
119 })?;
120
121 let Data::Enum(variants) = &cont.data else {
122 return Err(syn::Error::new(
123 Span::call_site(),
124 "JsonSchema_repr can only be used on enums",
125 ));
126 };
127
128 if let Some(non_unit_error) = variants.iter().find_map(|v| match v.style {
129 Style::Unit => None,
130 _ => Some(syn::Error::new_spanned(
131 v.original,
132 "JsonSchema_repr: must be a unit variant",
133 )),
134 }) {
135 return Err(non_unit_error);
136 }
137
138 let enum_ident = &cont.ident;
139 let variant_idents = variants.iter().map(|v| &v.ident);
140
141 let mut schema_expr = SchemaExpr::from(quote!({
142 let mut map = schemars::_private::serde_json::Map::new();
143 map.insert("type".into(), "integer".into());
144 map.insert(
145 "enum".into(),
146 schemars::_private::serde_json::Value::Array({
147 let mut enum_values = schemars::_private::alloc::vec::Vec::new();
148 #(enum_values.push((#enum_ident::#variant_idents as #repr_type).into());)*
149 enum_values
150 }),
151 );
152 schemars::Schema::from(map)
153 }));
154
155 cont.add_mutators(&mut schema_expr.mutators);
156
157 Ok(schema_expr)
158}
159
160fn expr_for_container_with(cont: &Container, with_attr: &WithAttr) -> SchemaExpr {
161 let (ty, type_def) = type_for_schema(cont, with_attr);
162
163 let mut schema_expr = SchemaExpr::from(quote! {
164 <#ty as schemars::JsonSchema>::json_schema(#GENERATOR)
165 });
166
167 schema_expr.definitions.extend(type_def);
168
169 schema_expr
170}
171
172fn expr_for_field(
173 cont: &Container,
174 field: &Field,
175 is_internal_tagged_enum_newtype: bool,
176) -> SchemaExpr {
177 let (ty, type_def) = type_for_field_schema(cont, field);
178 let span = field.original.span();
179
180 let schema_expr = if field.attrs.validation.required {
181 quote_spanned! {span=>
182 <#ty as schemars::JsonSchema>::_schemars_private_non_optional_json_schema(#GENERATOR)
183 }
184 } else if is_internal_tagged_enum_newtype {
185 quote_spanned! {span=>
186 schemars::_private::json_schema_for_internally_tagged_enum_newtype_variant::<#ty>(#GENERATOR)
187 }
188 } else {
189 quote_spanned! {span=>
190 #GENERATOR.subschema_for::<#ty>()
191 }
192 };
193 let mut schema_expr = SchemaExpr::from(schema_expr);
194
195 schema_expr.definitions.extend(type_def);
196 field.add_mutators(&mut schema_expr.mutators);
197
198 schema_expr
199}
200
201fn type_for_field_schema(cont: &Container, field: &Field) -> (syn::Type, Option<TokenStream>) {
202 match &field.attrs.with {
203 None => (field.ty.clone(), None),
204 Some(with_attr) => type_for_schema(cont, with_attr),
205 }
206}
207
208fn type_for_schema(cont: &Container, with_attr: &WithAttr) -> (syn::Type, Option<TokenStream>) {
209 match with_attr {
210 WithAttr::Type(ty) => (ty.clone(), None),
211 WithAttr::Function(fun) => {
212 let cont_name = &cont.ident;
213 let fn_name = fun.segments.last().unwrap().ident.to_string();
214 let (impl_generics, ty_generics, where_clause) = cont.generics.split_for_impl();
215
216 let type_def = quote_spanned! {fun.span()=>
217 struct _SchemarsSchemaWithFunction<T: ?::core::marker::Sized>(::core::marker::PhantomData<T>);
218
219 impl #impl_generics schemars::JsonSchema for _SchemarsSchemaWithFunction<#cont_name #ty_generics> #where_clause {
220 fn inline_schema() -> bool {
221 true
222 }
223
224 fn schema_name() -> schemars::_private::alloc::borrow::Cow<'static, str> {
225 schemars::_private::alloc::borrow::Cow::Borrowed(#fn_name)
226 }
227
228 fn schema_id() -> schemars::_private::alloc::borrow::Cow<'static, str> {
229 schemars::_private::alloc::borrow::Cow::Borrowed(::core::concat!(
230 "_SchemarsSchemaWithFunction/",
231 ::core::module_path!(),
232 "/",
233 ::core::stringify!(#fun)
234 ))
235 }
236
237 fn json_schema(generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
238 #fun(generator)
239 }
240 }
241 };
242
243 (
244 parse_quote!(_SchemarsSchemaWithFunction::<#cont_name #ty_generics>),
245 Some(type_def),
246 )
247 }
248 }
249}
250
251fn expr_for_enum(
252 cont: &Container,
253 variants: &[Variant],
254 cattrs: &serde_attr::Container,
255) -> SchemaExpr {
256 if variants.is_empty() {
257 return quote!(schemars::Schema::from(false)).into();
258 }
259 let deny_unknown_fields = cattrs.deny_unknown_fields();
260 let variants = variants.iter();
261
262 match cattrs.tag() {
263 TagType::External => expr_for_external_tagged_enum(cont, variants, deny_unknown_fields),
264 TagType::None => expr_for_untagged_enum(cont, variants, deny_unknown_fields),
265 TagType::Internal { tag } => {
266 expr_for_internal_tagged_enum(cont, variants, tag, deny_unknown_fields)
267 }
268 TagType::Adjacent { tag, content } => {
269 expr_for_adjacent_tagged_enum(cont, variants, tag, content, deny_unknown_fields)
270 }
271 }
272}
273
274fn expr_for_external_tagged_enum<'a>(
275 cont: &Container,
276 variants: impl Iterator<Item = &'a Variant<'a>>,
277 deny_unknown_fields: bool,
278) -> SchemaExpr {
279 let (unit_variants, complex_variants): (Vec<_>, Vec<_>) = variants.partition(|v| {
280 v.is_unit() && v.attrs.is_default() && !v.serde_attrs.untagged() && !cont.attrs.ref_variants
281 });
282 let add_unit_names = unit_variants.iter().map(|v| {
283 let name = v.name();
284 v.with_contract_check(quote! {
285 enum_values.push((#name).into());
286 })
287 });
288 let unit_schema = SchemaExpr::from(quote!({
289 let mut map = schemars::_private::serde_json::Map::new();
290 map.insert("type".into(), "string".into());
291 map.insert(
292 "enum".into(),
293 schemars::_private::serde_json::Value::Array({
294 let mut enum_values = schemars::_private::alloc::vec::Vec::new();
295 #(#add_unit_names)*
296 enum_values
297 }),
298 );
299 schemars::Schema::from(map)
300 }));
301
302 if complex_variants.is_empty() {
303 return unit_schema;
304 }
305
306 let mut schemas = Vec::new();
307 if !unit_variants.is_empty() {
308 schemas.push((None, unit_schema));
309 }
310
311 schemas.extend(complex_variants.into_iter().map(|variant| {
312 if variant.serde_attrs.untagged() {
313 return (
314 Some(variant),
315 expr_for_untagged_enum_variant(cont, variant, deny_unknown_fields, true),
316 );
317 }
318
319 let name = variant.name();
320
321 let mut schema_expr =
322 SchemaExpr::from(if variant.is_unit() && variant.attrs.with.is_none() {
323 quote! {
324 schemars::_private::new_unit_enum_variant(#name)
325 }
326 } else {
327 let sub_schema =
328 expr_for_untagged_enum_variant(cont, variant, deny_unknown_fields, false);
329 quote! {
330 schemars::_private::new_externally_tagged_enum_variant(#name, #sub_schema)
331 }
332 });
333
334 variant.add_mutators(&mut schema_expr.mutators);
335
336 (Some(variant), schema_expr)
337 }));
338
339 variant_subschemas(cont, true, schemas)
340}
341
342fn expr_for_internal_tagged_enum<'a>(
343 cont: &Container,
344 variants: impl Iterator<Item = &'a Variant<'a>>,
345 tag_name: &str,
346 deny_unknown_fields: bool,
347) -> SchemaExpr {
348 let variant_schemas = variants
349 .map(|variant| {
350 if variant.serde_attrs.untagged() {
351 return (Some(variant), expr_for_untagged_enum_variant(cont, variant, deny_unknown_fields, true))
352 }
353
354 let mut schema_expr = expr_for_internal_tagged_enum_variant(cont, variant, deny_unknown_fields);
355
356 let name = variant.name();
357 schema_expr.mutators.push(quote!(
358 schemars::_private::apply_internal_enum_variant_tag(&mut #SCHEMA, #tag_name, #name, #deny_unknown_fields);
359 ));
360
361 variant.add_mutators(&mut schema_expr.mutators);
362
363 (Some(variant), schema_expr)
364 })
365 .collect();
366
367 variant_subschemas(cont, true, variant_schemas)
368}
369
370fn expr_for_untagged_enum<'a>(
371 cont: &Container,
372 variants: impl Iterator<Item = &'a Variant<'a>>,
373 deny_unknown_fields: bool,
374) -> SchemaExpr {
375 let schemas = variants
376 .map(|variant| {
377 let schema_expr =
378 expr_for_untagged_enum_variant(cont, variant, deny_unknown_fields, true);
379
380 (Some(variant), schema_expr)
381 })
382 .collect();
383
384 variant_subschemas(cont, false, schemas)
387}
388
389fn expr_for_adjacent_tagged_enum<'a>(
390 cont: &Container,
391 variants: impl Iterator<Item = &'a Variant<'a>>,
392 tag_name: &str,
393 content_name: &str,
394 deny_unknown_fields: bool,
395) -> SchemaExpr {
396 let schemas = variants
397 .map(|variant| {
398 if variant.serde_attrs.untagged() {
399 return (
400 Some(variant),
401 expr_for_untagged_enum_variant(cont, variant, deny_unknown_fields, true),
402 );
403 }
404
405 let content_schema = if variant.is_unit() && variant.attrs.with.is_none() {
406 None
407 } else {
408 Some(expr_for_untagged_enum_variant(
409 cont,
410 variant,
411 deny_unknown_fields,
412 false,
413 ))
414 };
415
416 let (add_content_to_props, add_content_to_required) = content_schema
417 .map(|content_schema| {
418 (
419 quote!(#content_name: (#content_schema),),
420 quote!(#content_name,),
421 )
422 })
423 .unwrap_or_default();
424
425 let name = variant.name();
426 let tag_schema = quote! {
427 schemars::json_schema!({
428 "type": "string",
429 "const": #name,
430 })
431 };
432
433 let set_additional_properties = if deny_unknown_fields {
434 quote! {
435 "additionalProperties": false,
436 }
437 } else {
438 TokenStream::new()
439 };
440
441 let mut outer_schema = SchemaExpr::from(quote!(schemars::json_schema!({
442 "type": "object",
443 "properties": {
444 #tag_name: (#tag_schema),
445 #add_content_to_props
446 },
447 "required": [
448 #tag_name,
449 #add_content_to_required
450 ],
451 #set_additional_properties
454 })));
455
456 variant.add_mutators(&mut outer_schema.mutators);
457
458 (Some(variant), outer_schema)
459 })
460 .collect();
461
462 variant_subschemas(cont, true, schemas)
463}
464
465fn variant_subschemas(
468 cont: &Container,
469 mut unique: bool,
470 schemas: Vec<(Option<&Variant>, SchemaExpr)>,
471) -> SchemaExpr {
472 if schemas
473 .iter()
474 .any(|(v, _)| v.is_some_and(|v| v.serde_attrs.untagged()))
475 {
476 unique = false;
477 }
478
479 let keyword = if unique { "oneOf" } else { "anyOf" };
480 let add_schemas = schemas.into_iter().map(|(variant, mut schema)| {
481 if cont.attrs.ref_variants {
482 schema = enum_ref_variants(cont, variant, schema);
483 }
484
485 let add = quote! {
486 enum_values.push(#schema.to_value());
487 };
488 match variant {
489 Some(v) => v.with_contract_check(add),
490 None => add,
491 }
492 });
493 quote!({
494 let mut map = schemars::_private::serde_json::Map::new();
495 map.insert(
496 #keyword.into(),
497 schemars::_private::serde_json::Value::Array({
498 let mut enum_values = schemars::_private::alloc::vec::Vec::new();
499 #(#add_schemas)*
500 enum_values
501 }),
502 );
503 schemars::Schema::from(map)
504 })
505 .into()
506}
507
508fn enum_ref_variants(cont: &Container, variant: Option<&Variant>, expr: SchemaExpr) -> SchemaExpr {
509 let Some(variant) = variant else {
510 return expr;
511 };
512
513 let cont_name = &cont.ident;
514 let variant_name = variant.serde_attrs.name().deserialize_name();
516 let (impl_generics, ty_generics, where_clause) = cont.generics.split_for_impl();
517
518 let type_def = quote! {
519 struct _SchemarsRefVariant<T: ?::core::marker::Sized>(::core::marker::PhantomData<T>);
520
521 impl #impl_generics schemars::JsonSchema for _SchemarsRefVariant<#cont_name #ty_generics> #where_clause {
522 fn inline_schema() -> bool {
523 false
524 }
525
526 fn schema_name() -> schemars::_private::alloc::borrow::Cow<'static, str> {
527 schemars::_private::alloc::borrow::Cow::Borrowed(#variant_name)
528 }
529
530 fn schema_id() -> schemars::_private::alloc::borrow::Cow<'static, str> {
531 schemars::_private::alloc::borrow::Cow::Owned(
532 schemars::_private::alloc::format!(
533 "_SchemarsRefVariant/{}::{}",
534 <#cont_name #ty_generics as schemars::JsonSchema>::schema_id(),
535 #variant_name,
536 ))
537 }
538
539 fn json_schema(#GENERATOR: &mut schemars::SchemaGenerator) -> schemars::Schema {
540 #expr
541 }
542 }
543 };
544
545 let mut expr = SchemaExpr::from(
546 quote!(#GENERATOR.subschema_for::<_SchemarsRefVariant::<#cont_name #ty_generics>>()),
547 );
548
549 expr.definitions.push(type_def);
550
551 expr
552}
553
554fn expr_for_untagged_enum_variant(
558 cont: &Container,
559 variant: &Variant,
560 deny_unknown_fields: bool,
561 is_actually_untagged: bool,
562) -> SchemaExpr {
563 let mut schema_expr = if let Some(with_attr) = &variant.attrs.with {
564 let (ty, type_def) = type_for_schema(cont, with_attr);
565 let mut schema_expr = SchemaExpr::from(quote_spanned! {variant.original.span()=>
566 #GENERATOR.subschema_for::<#ty>()
567 });
568
569 schema_expr.definitions.extend(type_def);
570 schema_expr
571 } else {
572 match variant.style {
573 Style::Unit => expr_for_unit_struct(),
574 Style::Newtype => expr_for_field(cont, &variant.fields[0], false),
575 Style::Tuple => expr_for_tuple_struct(cont, &variant.fields),
576 Style::Struct => expr_for_struct(
577 cont,
578 &variant.fields,
579 &SerdeDefault::None,
580 deny_unknown_fields,
581 ),
582 }
583 };
584
585 if is_actually_untagged {
586 if variant.attrs.common.title.is_none() {
587 let title = variant.name();
588 schema_expr.mutators.push(quote! {
589 if #GENERATOR.settings().untagged_enum_variant_titles {
590 #SCHEMA.insert("title".into(), #title.into());
591 }
592 });
593 }
594
595 variant.add_mutators(&mut schema_expr.mutators);
596 }
597
598 schema_expr
599}
600
601fn expr_for_internal_tagged_enum_variant(
602 cont: &Container,
603 variant: &Variant,
604 deny_unknown_fields: bool,
605) -> SchemaExpr {
606 if let Some(with_attr) = &variant.attrs.with {
607 let (ty, type_def) = type_for_schema(cont, with_attr);
608 let mut schema_expr = SchemaExpr::from(quote_spanned! {variant.original.span()=>
609 <#ty as schemars::JsonSchema>::json_schema(#GENERATOR)
610 });
611
612 schema_expr.definitions.extend(type_def);
613
614 return schema_expr;
615 }
616
617 match variant.style {
618 Style::Unit => expr_for_unit_struct(),
619 Style::Newtype => expr_for_field(cont, &variant.fields[0], true),
620 Style::Tuple => expr_for_tuple_struct(cont, &variant.fields),
621 Style::Struct => expr_for_struct(
622 cont,
623 &variant.fields,
624 &SerdeDefault::None,
625 deny_unknown_fields,
626 ),
627 }
628}
629
630fn expr_for_unit_struct() -> SchemaExpr {
631 quote! {
632 #GENERATOR.subschema_for::<()>()
633 }
634 .into()
635}
636
637fn expr_for_newtype_struct(cont: &Container, field: &Field) -> SchemaExpr {
638 expr_for_field(cont, field, false)
639}
640
641fn expr_for_tuple_struct(cont: &Container, fields: &[Field]) -> SchemaExpr {
642 let fields: Vec<_> = fields
643 .iter()
644 .map(|f| {
645 let field_expr = expr_for_field(cont, f, false);
646 f.with_contract_check(quote! {
647 prefix_items.push((#field_expr).to_value());
648 })
649 })
650 .collect();
651
652 let max_len = fields.len();
653
654 quote!({
657 let mut prefix_items = schemars::_private::alloc::vec::Vec::<schemars::_private::serde_json::Value>::with_capacity(#max_len);
658 #(#fields)*
659 let len = prefix_items.len();
660
661 let mut map = schemars::_private::serde_json::Map::new();
662 map.insert("type".into(), "array".into());
663 if !prefix_items.is_empty() {
664 map.insert("prefixItems".into(), prefix_items.into());
665 map.insert("minItems".into(), len.into());
666 }
667 map.insert("maxItems".into(), len.into());
668
669 schemars::Schema::from(map)
670 })
671 .into()
672}
673
674fn expr_for_struct(
675 cont: &Container,
676 fields: &[Field],
677 default: &SerdeDefault,
678 deny_unknown_fields: bool,
679) -> SchemaExpr {
680 let set_container_default = match default {
681 SerdeDefault::None => None,
682 SerdeDefault::Default => Some(quote!(let #STRUCT_DEFAULT = Self::default();)),
683 SerdeDefault::Path(path) => Some(quote!(let #STRUCT_DEFAULT = #path();)),
684 };
685
686 let properties: Vec<TokenStream> = fields
688 .iter()
689 .filter(|f| !f.serde_attrs.skip_deserializing() || !f.serde_attrs.skip_serializing())
690 .map(|field| {
691 if field.serde_attrs.flatten() {
692 let (ty, type_def) = type_for_field_schema(cont, field);
693
694 let required = field.attrs.validation.required;
695 let mut schema_expr = SchemaExpr::from(quote_spanned! {ty.span()=>
696 schemars::_private::json_schema_for_flatten::<#ty>(#GENERATOR, #required)
697 });
698
699 schema_expr.definitions.extend(type_def);
700
701 field.with_contract_check(quote! {
702 schemars::_private::flatten(&mut #SCHEMA, #schema_expr);
703 })
704 } else {
705 let mut schema_expr = expr_for_field(cont, field, false);
706
707 if let Some(default) = field_default_expr(field, set_container_default.is_some()) {
708 schema_expr.mutators.push(quote! {
709 #default.and_then(|d| schemars::_schemars_maybe_to_value!(d))
710 .map(|d| #SCHEMA.insert("default".into(), d));
711 });
712 }
713
714 let name = field.name();
715 let (ty, type_def) = type_for_field_schema(cont, field);
716
717 if type_def.is_some() {
718 assert!(!schema_expr.definitions.is_empty());
719 }
720
721 let has_default = set_container_default.is_some() || !field.serde_attrs.default().is_none();
722 let has_skip_serialize_if = field.serde_attrs.skip_serializing_if().is_some();
723 let required_attr = field.attrs.validation.required;
724
725 let is_optional = if has_skip_serialize_if && has_default {
726 quote!(true)
727 } else if !has_skip_serialize_if && !has_default && !required_attr {
728 quote!(#GENERATOR.contract().is_deserialize() && <#ty as schemars::JsonSchema>::_schemars_private_is_option())
729 } else {
730 quote!(if #GENERATOR.contract().is_deserialize() {
731 #has_default || (!#required_attr && <#ty as schemars::JsonSchema>::_schemars_private_is_option())
732 } else {
733 #has_skip_serialize_if
734 })
735 };
736
737 let definitions = core::mem::take(&mut schema_expr.definitions);
740 field.with_contract_check(quote!({
741 #(#definitions)*
742 schemars::_private::insert_object_property(&mut #SCHEMA, #name, #is_optional, #schema_expr);
743 }))
744 }
745 })
746 .collect();
747
748 let set_additional_properties = if deny_unknown_fields {
749 quote! {
750 "additionalProperties": false,
751 }
752 } else {
753 TokenStream::new()
754 };
755
756 SchemaExpr {
757 definitions: set_container_default.into_iter().collect(),
758 creator: quote!(schemars::json_schema!({
759 "type": "object",
760 #set_additional_properties
761 })),
762 mutators: properties,
763 }
764}
765
766fn field_default_expr(field: &Field, container_has_default: bool) -> Option<TokenStream> {
767 let field_default = field.serde_attrs.default();
768 if field.serde_attrs.skip_serializing() || (field_default.is_none() && !container_has_default) {
769 return None;
770 }
771
772 let ty = field.ty;
773 let default_expr = match field_default {
774 SerdeDefault::None => {
775 let member = &field.member;
776 quote!(#STRUCT_DEFAULT.#member)
777 }
778 SerdeDefault::Default => quote!(<#ty>::default()),
779 SerdeDefault::Path(path) => quote!(#path()),
780 };
781
782 let default_expr = if let Some(skip_if) = field.serde_attrs.skip_serializing_if() {
783 quote! {
784 {
785 let default = #default_expr;
786 if #skip_if(&default) {
787 None
788 } else {
789 Some(default)
790 }
791 }
792 }
793 } else {
794 quote!(Some(#default_expr))
795 };
796
797 Some(if let Some(ser_with) = field.serde_attrs.serialize_with() {
798 quote! {
799 {
800 struct _SchemarsDefaultSerialize<T>(T);
801
802 impl serde::Serialize for _SchemarsDefaultSerialize<#ty>
803 {
804 fn serialize<S>(&self, serializer: S) -> ::core::result::Result<S::Ok, S::Error>
805 where
806 S: serde::Serializer
807 {
808 #ser_with(&self.0, serializer)
809 }
810 }
811
812 #default_expr.map(|d| _SchemarsDefaultSerialize(d))
813 }
814 }
815 } else {
816 default_expr
817 })
818}