@@ -334,13 +334,17 @@ def to_obj(
334334 named : bool ,
335335 reuse_instances : Optional [bool ] = None ,
336336 convert_sets : Optional [bool ] = None ,
337+ skip_none : bool = False ,
337338 c : Optional [Any ] = None ,
338339) -> Any :
339340 def serializable_to_obj (object : Any ) -> Any :
340341 serde_scope : Scope = getattr (object , SERDE_SCOPE )
341342 func_name = TO_DICT if named else TO_ITER
342343 return serde_scope .funcs [func_name ](
343- object , reuse_instances = reuse_instances , convert_sets = convert_sets
344+ object ,
345+ reuse_instances = reuse_instances ,
346+ convert_sets = convert_sets ,
347+ skip_none = skip_none ,
344348 )
345349
346350 try :
@@ -349,6 +353,7 @@ def serializable_to_obj(object: Any) -> Any:
349353 named = named ,
350354 reuse_instances = reuse_instances ,
351355 convert_sets = convert_sets ,
356+ skip_none = skip_none ,
352357 )
353358
354359 # If a class in the argument is a non-dataclass class e.g. Union[Foo, Bar],
@@ -377,7 +382,11 @@ def serializable_to_obj(object: Any) -> Any:
377382 return {k : thisfunc (v ) for k , v in o .items ()}
378383 elif is_str_serializable_instance (o ) or is_datetime_instance (o ):
379384 return CACHE .serialize (
380- c or o .__class__ , o , reuse_instances = reuse_instances , convert_sets = convert_sets
385+ c or o .__class__ ,
386+ o ,
387+ reuse_instances = reuse_instances ,
388+ convert_sets = convert_sets ,
389+ skip_none = skip_none ,
381390 )
382391
383392 return o
@@ -398,6 +407,7 @@ def to_tuple(
398407 c : Optional [type [Any ]] = None ,
399408 reuse_instances : Optional [bool ] = None ,
400409 convert_sets : Optional [bool ] = None ,
410+ skip_none : bool = False ,
401411) -> tuple [Any , ...]:
402412 """
403413 Serialize object into tuple.
@@ -419,7 +429,12 @@ def to_tuple(
419429 [(10, 'foo', 100.0, True), (20, 'foo', 100.0, True)]
420430 """
421431 return to_obj ( # type: ignore
422- o , named = False , c = c , reuse_instances = reuse_instances , convert_sets = convert_sets
432+ o ,
433+ named = False ,
434+ c = c ,
435+ reuse_instances = reuse_instances ,
436+ convert_sets = convert_sets ,
437+ skip_none = skip_none ,
423438 )
424439
425440
@@ -435,6 +450,7 @@ def to_dict(
435450 c : Optional [type [Any ]] = None ,
436451 reuse_instances : Optional [bool ] = None ,
437452 convert_sets : Optional [bool ] = None ,
453+ skip_none : bool = False ,
438454) -> dict [Any , Any ]:
439455 """
440456 Serialize object into python dictionary. This function ensures that the dataclass's fields are
@@ -450,6 +466,8 @@ def to_dict(
450466 deserialization. When `convert_sets` is set to True, pyserde will convert sets to lists during
451467 serialization and back to sets during deserialization. This is useful for data formats that
452468 do not natively support sets.
469+ * `skip_none`: When set to True, any field in the class with a None value is excluded from the
470+ serialized output. Defaults to False.
453471
454472 >>> from serde import serde
455473 >>> @serde
@@ -470,7 +488,12 @@ def to_dict(
470488 [{'i': 10, 's': 'foo', 'f': 100.0, 'b': True}, {'i': 20, 's': 'foo', 'f': 100.0, 'b': True}]
471489 """
472490 return to_obj ( # type: ignore
473- o , named = True , c = c , reuse_instances = reuse_instances , convert_sets = convert_sets
491+ o ,
492+ named = True ,
493+ c = c ,
494+ reuse_instances = reuse_instances ,
495+ convert_sets = convert_sets ,
496+ skip_none = skip_none ,
474497 )
475498
476499
@@ -524,7 +547,7 @@ def sefields(cls: type[Any], serialize_class_var: bool = False) -> Iterator[SeFi
524547 loader = jinja2 .DictLoader (
525548 {
526549 "dict" : """
527- def {{func}}(obj, reuse_instances = None, convert_sets = None):
550+ def {{func}}(obj, reuse_instances = None, convert_sets = None, skip_none = False ):
528551 if reuse_instances is None:
529552 reuse_instances = {{serde_scope.reuse_instances_default}}
530553 if convert_sets is None:
@@ -534,21 +557,25 @@ def {{func}}(obj, reuse_instances = None, convert_sets = None):
534557
535558 res = {}
536559 {% for f in fields -%}
560+ subres = {{rvalue(f)}}
537561 {% if not f.skip -%}
538562 {% if f.skip_if -%}
539- subres = {{rvalue(f)}}
540563 if not {{f.skip_if.name}}(subres):
541564 {{lvalue(f)}} = subres
542565 {% else -%}
543- {{lvalue(f)}} = {{rvalue(f)}}
566+ if skip_none:
567+ if subres is not None:
568+ {{lvalue(f)}} = subres
569+ else:
570+ {{lvalue(f)}} = subres
544571 {% endif -%}
545572 {% endif %}
546573
547574 {% endfor -%}
548575 return res
549576""" ,
550577 "iter" : """
551- def {{func}}(obj, reuse_instances=None, convert_sets=None):
578+ def {{func}}(obj, reuse_instances=None, convert_sets=None, skip_none=False ):
552579 if reuse_instances is None:
553580 reuse_instances = {{serde_scope.reuse_instances_default}}
554581 if convert_sets is None:
0 commit comments