Skip to content

Commit e9586d2

Browse files
committed
Refactor model parsing for nullable and array properties
Improves the From() method in Model.cs.twig to handle nullable and array properties more robustly, using helper macros for parsing arrays and sub-schemas. This change ensures correct handling of optional fields and type conversions, reducing runtime errors and improving code maintainability. Also removes an unnecessary blank line in ServiceTemplate.cs.twig.
1 parent b071cbc commit e9586d2

File tree

2 files changed

+38
-8
lines changed

2 files changed

+38
-8
lines changed

templates/dotnet/Package/Models/Model.cs.twig

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
{% macro sub_schema(property) %}{% if property.sub_schema %}{% if property.type == 'array' %}List<{{property.sub_schema | caseUcfirst | overrideIdentifier}}>{% else %}{{property.sub_schema | caseUcfirst | overrideIdentifier}}{% endif %}{% else %}{{property | typeName}}{% endif %}{% if not property.required %}?{% endif %}{% endmacro %}
22
{% macro property_name(definition, property) %}{{ property.name | caseUcfirst | removeDollarSign | escapeKeyword }}{% endmacro %}
3+
{% macro array_source(src, required) %}{% if required %}((IEnumerable<object>){{ src | raw }}){% else %}({{ src | raw }} as IEnumerable<object> ?? Array.Empty<object>()){% endif %}{% endmacro %}
4+
{%~ macro parse_primitive_array(items_type, src, required) -%}
5+
{{ _self.array_source(src, required) }}.Select(x => {% if items_type == "string" %}x?.ToString(){% elseif items_type == "integer" %}{% if not required %}x == null ? (long?)null : {% endif %}Convert.ToInt64(x){% elseif items_type == "number" %}{% if not required %}x == null ? (double?)null : {% endif %}Convert.ToDouble(x){% elseif items_type == "boolean" %}{% if not required %}x == null ? (bool?)null : {% endif %}(bool)x{% else %}x{% endif %}){% if required and items_type == "string" %}.Where(x => x != null){% endif %}.ToList()!
6+
{%- endmacro -%}
7+
{%~ macro parse_subschema_array(sub_schema_name, src, required) -%}
8+
{{ _self.array_source(src, required) }}.Select(it => {{ sub_schema_name | caseUcfirst | overrideIdentifier }}.From(map: (Dictionary<string, object>)it)).ToList()
9+
{%- endmacro -%}
310
using System;
411
using System.Linq;
512
using System.Collections.Generic;
@@ -38,25 +45,49 @@ namespace {{ spec.title | caseUcfirst }}.Models
3845

3946
public static {{ definition.name | caseUcfirst | overrideIdentifier }} From(Dictionary<string, object> map) => new {{ definition.name | caseUcfirst | overrideIdentifier }}(
4047
{%~ for property in definition.properties %}
48+
{%~ set v = 'v' ~ loop.index0 %}
49+
{%~ set mapAccess = 'map["' ~ property.name ~ '"]' %}
4150
{{ property.name | caseCamel | escapeKeyword | removeDollarSign }}:{{' '}}
42-
{%- if not property.required -%}map.ContainsKey("{{ property.name }}") ? {% endif %}
51+
{%- if not property.required -%}map.TryGetValue("{{ property.name }}", out var {{ v }}) ? {% endif %}
4352
{%- if property.sub_schema %}
4453
{%- if property.type == 'array' -%}
45-
((IEnumerable<object>)map["{{ property.name }}"]).Select(it => {{ property.sub_schema | caseUcfirst | overrideIdentifier }}.From(map: (Dictionary<string, object>)it)).ToList()
54+
{%- if property.required -%}
55+
{{ _self.parse_subschema_array(property.sub_schema, mapAccess, true) }}
56+
{%- else -%}
57+
{{ _self.parse_subschema_array(property.sub_schema, v, false) }}
58+
{%- endif %}
4659
{%- else -%}
47-
{{ property.sub_schema | caseUcfirst | overrideIdentifier }}.From(map: (Dictionary<string, object>)map["{{ property.name }}"])
60+
{%- if property.required -%}
61+
{{ property.sub_schema | caseUcfirst | overrideIdentifier }}.From(map: (Dictionary<string, object>){{ mapAccess | raw }})
62+
{%- else -%}
63+
({{ v }} as Dictionary<string, object>) is { } obj
64+
? {{ property.sub_schema | caseUcfirst | overrideIdentifier }}.From(map: obj)
65+
: null
66+
{%- endif %}
4867
{%- endif %}
4968
{%- else %}
5069
{%- if property.type == 'array' -%}
51-
((IEnumerable<object>)map["{{ property.name }}"]).Select(x => {% if property.items.type == "string" %}x?.ToString(){% elseif property.items.type == "integer" %}{% if not property.required %}x == null ? (long?)null : {% endif %}Convert.ToInt64(x){% elseif property.items.type == "number" %}{% if not property.required %}x == null ? (double?)null : {% endif %}Convert.ToDouble(x){% elseif property.items.type == "boolean" %}{% if not property.required %}x == null ? (bool?)null : {% endif %}(bool)x{% else %}x{% endif %}).{% if property.items.type == "string" and property.required %}Where(x => x != null).{% endif %}ToList()!
70+
{%- if property.required -%}
71+
{{ _self.parse_primitive_array(property.items.type, mapAccess, true) }}
72+
{%- else -%}
73+
{{ _self.parse_primitive_array(property.items.type, v, false) }}
74+
{%- endif -%}
5275
{%- else %}
5376
{%- if property.type == "integer" or property.type == "number" %}
54-
{%- if not property.required -%}map["{{ property.name }}"] == null ? null : {% endif %}Convert.To{% if property.type == "integer" %}Int64{% else %}Double{% endif %}(map["{{ property.name }}"])
77+
{%- if not property.required -%}Convert.To{% if property.type == "integer" %}Int64{% else %}Double{% endif %}({{ v }}){% else %}Convert.To{% if property.type == "integer" %}Int64{% else %}Double{% endif %}({{ mapAccess | raw }}){%- endif %}
5578
{%- else %}
5679
{%- if property.type == "boolean" -%}
57-
({{ property | typeName }}{% if not property.required %}?{% endif %})map["{{ property.name }}"]
80+
{%- if not property.required -%}
81+
({{ property | typeName }}?){{ v }}
82+
{%- else -%}
83+
({{ property | typeName }}){{ mapAccess | raw }}
84+
{%- endif %}
5885
{%- else -%}
59-
map["{{ property.name }}"]{% if not property.required %}?{% endif %}.ToString()
86+
{%- if not property.required -%}
87+
{{ v }}?.ToString()
88+
{%- else -%}
89+
{{ mapAccess | raw }}.ToString()
90+
{%- endif %}
6091
{%- endif %}
6192
{%~ endif %}
6293
{%~ endif %}

templates/dotnet/Package/Services/ServiceTemplate.cs.twig

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
{% import 'dotnet/base/utils.twig' as utils %}
2-
32
using System;
43
using System.Collections.Generic;
54
using System.Linq;

0 commit comments

Comments
 (0)