Пример #1
0
        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();
            }
        }