Skip to content

Commit 0ec5c40

Browse files
authored
Explicitly check for null values in C# jsonization (#525)
We explicitly check that both optional and required properties can not be set to ``null``. The optional properties should be explicitly absent from the object by specification, and thus ``null`` is not an acceptable value for optional properties.
1 parent b14237b commit 0ec5c40

File tree

2 files changed

+1931
-301
lines changed

2 files changed

+1931
-301
lines changed

aas_core_codegen/csharp/jsonization/_generate.py

+37-11
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ def _generate_from_method_for_interface(
8585
if (obj == null)
8686
{{
8787
{I}error = new Reporting.Error(
88-
{II}"Expected Nodes.JsonObject, but got {{node.GetType()}}");
88+
{II}$"Expected Nodes.JsonObject, but got {{node.GetType()}}");
8989
{I}return null;
9090
}}"""
9191
),
@@ -336,6 +336,42 @@ def _generate_deserialize_constructor_argument(
336336
else:
337337
assert_never(arg.type_annotation)
338338

339+
# NOTE (mristin):
340+
# We need to add a prologue to the parsing body to explicitly check for null
341+
# values as the null values are not allowed for optional properties by
342+
# specification.
343+
if isinstance(arg.type_annotation, intermediate.OptionalTypeAnnotation):
344+
parse_block = Stripped(
345+
f"""\
346+
if (keyValue.Value == null)
347+
{{
348+
{I}error = new Reporting.Error(
349+
{II}"Expected optional property to be absent, " +
350+
{II}"but got null instead");
351+
{I}error.PrependSegment(
352+
{II}new Reporting.NameSegment(
353+
{III}{json_literal}));
354+
{I}return null;
355+
}}
356+
357+
{parse_block}"""
358+
)
359+
else:
360+
parse_block = Stripped(
361+
f"""\
362+
if (keyValue.Value == null)
363+
{{
364+
{I}error = new Reporting.Error(
365+
{II}"Unexpected null for a required property");
366+
{I}error.PrependSegment(
367+
{II}new Reporting.NameSegment(
368+
{III}{json_literal}));
369+
{I}return null;
370+
}}
371+
372+
{parse_block}"""
373+
)
374+
339375
return parse_block, None
340376

341377

@@ -398,21 +434,11 @@ def _generate_from_method_for_class(
398434
assert case_body is not None
399435
json_name = naming.json_property(arg.name)
400436

401-
# NOTE (mristin, 2022-07-23):
402-
# We put ``if (keyValue.Value != null)`` here instead of the outer loop
403-
# since we want to detect the unexpected additional properties even
404-
# though their value can be set to null.
405-
406437
cases.append(
407438
Stripped(
408439
f"""\
409440
case {csharp_common.string_literal(json_name)}:
410441
{{
411-
{I}if (keyValue.Value == null)
412-
{I}{{
413-
{II}continue;
414-
{I}}}
415-
416442
{I}{indent_but_first_line(case_body, I)}
417443
{I}break;
418444
}}"""

0 commit comments

Comments
 (0)