private static void DeserializeIntoVariableMayBeObject(this CodeWriter writer, JsonSerialization serialization, Action <CodeWriter, CodeWriterDelegate> valueCallback, CodeWriterDelegate element, Dictionary <ObjectTypeProperty, CodeWriterDeclaration>?propertyVariables = null) { if (serialization is JsonObjectSerialization obj) { var itemVariable = new CodeWriterDeclaration("property"); if (propertyVariables == null) { // this is the first level of object hierarchy // collect all properties and initialize the dictionary propertyVariables = new Dictionary <ObjectTypeProperty, CodeWriterDeclaration>(); CollectProperties(propertyVariables, obj); foreach (var variable in propertyVariables) { var objectTypeProperty = variable.Key; writer.Line($"{objectTypeProperty.Declaration.Type} {variable.Value:D} = default;"); } } var dictionaryVariable = new CodeWriterDeclaration("additionalPropertiesDictionary"); var objAdditionalProperties = obj.AdditionalProperties; if (objAdditionalProperties != null) { writer.Line($"{objAdditionalProperties.Type} {dictionaryVariable:D} = default;"); } using (writer.Scope($"foreach (var {itemVariable:D} in {element}.EnumerateObject())")) { foreach (JsonPropertySerialization property in obj.Properties) { CSharpType?type = property.Property?.Declaration.Type; bool hasNullableType = type != null && type.IsNullable; void WriteNullCheck() { using (writer.Scope($"if ({itemVariable.ActualName}.Value.ValueKind == {typeof(JsonValueKind)}.Null)")) { writer.Append($"continue;"); } } writer.Append($"if({itemVariable.ActualName}.NameEquals({property.Name:L}))"); using (writer.Scope()) { if (hasNullableType) { WriteNullCheck(); } if (property.Property != null) { // Reading a property value writer.DeserializeIntoVariable( property.ValueSerialization, (w, v) => w.Line($"{propertyVariables[property.Property]} = {v};"), w => w.Append($"{itemVariable.ActualName}.Value")); } else { // Reading a nested object writer.DeserializeIntoVariableMayBeObject( property.ValueSerialization, (w, v) => { }, w => w.Append($"{itemVariable.ActualName}.Value"), propertyVariables); } writer.Line($"continue;"); } } if (objAdditionalProperties != null) { writer.Line($"{dictionaryVariable} ??= new {objAdditionalProperties.Type}();"); writer.DeserializeValue( objAdditionalProperties.ValueSerialization, w => w.Append($"{itemVariable}.Value"), (w, v) => w.Line($"{dictionaryVariable}.Add({itemVariable}.Name, {v});")); } } if (objAdditionalProperties != null) { writer.Line($"{propertyVariables[objAdditionalProperties.Property]} = {dictionaryVariable};"); } if (obj.Type != null) { var initializers = new List <ObjectPropertyInitializer>(); foreach (var variable in propertyVariables) { var property = variable.Key; initializers.Add(new ObjectPropertyInitializer( property, new Reference(variable.Value.ActualName, property.Declaration.Type))); } valueCallback(writer, w => w.WriteInitialization((ObjectType)obj.Type.Implementation, initializers)); } } else { writer.DeserializeIntoVariableWithNullHandling(serialization, valueCallback, element); } }