public static void ToSerializeCall(this CodeWriter writer, JsonSerialization serialization, CodeWriterDelegate name, CodeWriterDelegate?writerName = null) { writerName ??= w => w.AppendRaw("writer"); switch (serialization) { case JsonArraySerialization array: writer.Line($"{writerName}.WriteStartArray();"); var collectionItemVariable = new CodeWriterDeclaration("item"); using (writer.Scope($"foreach (var {collectionItemVariable:D} in {name})")) { writer.ToSerializeCall( array.ValueSerialization, w => w.Append(collectionItemVariable), writerName); } writer.Line($"{writerName}.WriteEndArray();"); return; case JsonDictionarySerialization dictionary: writer.Line($"{writerName}.WriteStartObject();"); var dictionaryItemVariable = new CodeWriterDeclaration("item"); using (writer.Scope($"foreach (var {dictionaryItemVariable:D} in {name})")) { writer.Line($"{writerName}.WritePropertyName({dictionaryItemVariable}.Key);"); writer.ToSerializeCall( dictionary.ValueSerialization, w => w.Append($"{dictionaryItemVariable}.Value"), writerName); } writer.Line($"{writerName}.WriteEndObject();"); return; case JsonObjectSerialization obj: writer.Line($"{writerName}.WriteStartObject();"); foreach (JsonPropertySerialization property in obj.Properties) { bool hasNullableType = property.Property?.Declaration.Type.IsNullable == true; bool emptyAsUndefined = property.Property?.EmptyAsUndefined == true; CodeWriter.CodeWriterScope?scope = default; if (hasNullableType || emptyAsUndefined) { var propertyName = property.Property !.Declaration.Name; writer.Append($"if ("); if (hasNullableType) { writer.Append($"{propertyName} != null"); } if (emptyAsUndefined) { if (hasNullableType) { writer.Append($" && "); } writer.UseNamespace(typeof(Enumerable).Namespace !); writer.Append($"{propertyName}.Any()"); } writer.Append($")"); scope = writer.Scope(); } using (scope) { writer.Line($"{writerName}.WritePropertyName({property.Name:L});"); writer.ToSerializeCall( property.ValueSerialization, w => w.Append($"{property.Property?.Declaration.Name}")); } } if (obj.AdditionalProperties != null) { var itemVariable = new CodeWriterDeclaration("item"); using (writer.Scope($"foreach (var {itemVariable:D} in {obj.AdditionalProperties.Property.Declaration.Name})")) { writer.Line($"{writerName}.WritePropertyName({itemVariable}.Key);"); writer.ToSerializeCall( obj.AdditionalProperties.ValueSerialization, w => w.Append($"{itemVariable}.Value"), writerName); } } writer.Line($"{writerName}.WriteEndObject();"); return; case JsonValueSerialization valueSerialization: writer.UseNamespace(typeof(Utf8JsonWriterExtensions).Namespace !); if (valueSerialization.Type.IsFrameworkType) { var frameworkType = valueSerialization.Type.FrameworkType; if (frameworkType == typeof(JsonElement)) { writer.Line($"{name}.WriteTo({writerName});"); return; } bool writeFormat = false; writer.Append($"{writerName}."); if (frameworkType == typeof(decimal) || frameworkType == typeof(double) || frameworkType == typeof(float) || frameworkType == typeof(long) || frameworkType == typeof(int) || frameworkType == typeof(short)) { writer.AppendRaw("WriteNumberValue"); } else if (frameworkType == typeof(object)) { writer.AppendRaw("WriteObjectValue"); } else if (frameworkType == typeof(string) || frameworkType == typeof(char) || frameworkType == typeof(Guid)) { writer.AppendRaw("WriteStringValue"); } else if (frameworkType == typeof(bool)) { writer.AppendRaw("WriteBooleanValue"); } else if (frameworkType == typeof(byte[])) { writer.AppendRaw("WriteBase64StringValue"); writeFormat = true; } else if (frameworkType == typeof(DateTimeOffset) || frameworkType == typeof(DateTime) || frameworkType == typeof(TimeSpan)) { if (valueSerialization.Format == SerializationFormat.DateTime_Unix) { writer.AppendRaw("WriteNumberValue"); } else { writer.AppendRaw("WriteStringValue"); } writeFormat = true; } writer.Append($"({name}") .AppendNullableValue(valueSerialization.Type); if (writeFormat && valueSerialization.Format.ToFormatSpecifier() is string formatString) { writer.Append($", {formatString:L}"); } writer.LineRaw(");"); return; } switch (valueSerialization.Type.Implementation) { case ObjectType _: writer.Line($"{writerName}.WriteObjectValue({name});"); return; case EnumType clientEnum: writer.Append($"{writerName}.WriteStringValue({name}") .AppendNullableValue(valueSerialization.Type) .AppendEnumToString(clientEnum) .Line($");"); return; } throw new NotSupportedException(); default: throw new NotSupportedException(); } }