Skip to content

Commit

Permalink
feat: XmlSerializer skip optional nillable elements
Browse files Browse the repository at this point in the history
  • Loading branch information
tefra committed Jul 28, 2024
1 parent 6eccffb commit 00d910f
Show file tree
Hide file tree
Showing 4 changed files with 11 additions and 3 deletions.
4 changes: 2 additions & 2 deletions docs/models/fields.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,12 @@ The namespace name of the XML element or attribute.
### `nillable`

Specify if the field has to be present in the serialized result even when it doesn't
have any meaningful content.
have any meaningful content. If the field is not required the serializer will ignore it.

```python
>>> @dataclass
... class Root:
... first: Optional[str] = field(metadata={"nillable": True}, default=None)
... first: Optional[str] = field(metadata={"nillable": True, "required": True}, default=None)
... second: Optional[str] = field(default=None)
...
>>> print(serializer.render(Root()))
Expand Down
2 changes: 2 additions & 0 deletions tests/fixtures/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,8 @@ class SequentialType:
x4: Optional[int] = field(
default=None, metadata={"type": "Element", "sequence": 2}
)
x5: Optional[str] = field(default=None, metadata={"type": "Element", "nillable": True})
x6: Optional[str] = field(default=None, metadata={"type": "Element", "nillable": True, "required": True})


@dataclass
Expand Down
6 changes: 6 additions & 0 deletions tests/formats/dataclass/serializers/test_mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -693,6 +693,10 @@ def test_convert_choice_with_derived_dataclass(self):
expected = [
("start", "a"),
("attr", "a0", "foo"),
("start", "{xsdata}x6"),
("attr", QNames.XSI_NIL, "true"),
("data", None),
("end", "{xsdata}x6"),
("end", "a"),
]

Expand Down Expand Up @@ -814,6 +818,7 @@ def test_next_value(self):
x2 = next(meta.find_children("x2"))
x3 = next(meta.find_children("x3"))
x4 = next(meta.find_children("x4"))
x6 = next(meta.find_children("x6"))

actual = self.generator.next_value(obj, meta)
expected = [
Expand All @@ -825,6 +830,7 @@ def test_next_value(self):
(x1, 4),
(x3, 9),
(x4, 10),
(x6, None),
]

self.assertIsInstance(actual, Generator)
Expand Down
2 changes: 1 addition & 1 deletion xsdata/formats/dataclass/serializers/mixins.py
Original file line number Diff line number Diff line change
Expand Up @@ -933,7 +933,7 @@ def next_value(cls, obj: Any, meta: XmlMeta) -> Iterator[Tuple[XmlVar, Any]]:

if var.sequence is None:
value = getattr(obj, var.name)
if value is not None or var.nillable:
if value is not None or (var.nillable and var.required):
yield var, value
index += 1
continue
Expand Down

0 comments on commit 00d910f

Please sign in to comment.