File: TemplateSearchCache\TemplatePackageSearchData.Json.cs
Web Access
Project: src\src\sdk\src\TemplateEngine\Microsoft.TemplateSearch.Common\Microsoft.TemplateSearch.Common.csproj (Microsoft.TemplateSearch.Common)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

#if NET7_0_OR_GREATER
using System.Diagnostics.CodeAnalysis;
#endif
using System.Text.Json;
using System.Text.Json.Nodes;
using Microsoft.Extensions.Logging;
using Microsoft.TemplateEngine;

namespace Microsoft.TemplateSearch.Common
{
    [System.Text.Json.Serialization.JsonConverter(typeof(TemplatePackageSearchDataJsonConverter))]
    public partial class TemplatePackageSearchData
    {
        internal TemplatePackageSearchData(JsonObject jObject, ILogger logger, IReadOnlyDictionary<string, Func<object, object>>? additionalDataReaders = null)
        {
            if (jObject is null)
            {
                throw new ArgumentNullException(nameof(jObject));
            }

            if (logger is null)
            {
                throw new ArgumentNullException(nameof(logger));
            }
            string? name = jObject.ToString(nameof(Name));
            Name = !string.IsNullOrWhiteSpace(name) ? name!
                : throw new ArgumentException($"{nameof(jObject)} doesn't have {nameof(Name)} property or it is not a string.", nameof(jObject));
            Version = jObject.ToString(nameof(Version));
            TotalDownloads = jObject.ToInt32(nameof(TotalDownloads));
            Owners = jObject.Get<JsonNode>(nameof(Owners)).JTokenStringOrArrayToCollection([]);
            Reserved = jObject.ToBool(nameof(Reserved));

            Description = jObject.ToString(nameof(Description));
            IconUrl = jObject.ToString(nameof(IconUrl));

            JsonArray? templatesData = jObject.Get<JsonArray>(nameof(Templates))
                ?? throw new ArgumentException($"{nameof(jObject)} doesn't have {nameof(Templates)} property or it is not an array.", nameof(jObject));
            List<TemplateSearchData> templates = new List<TemplateSearchData>();
            foreach (JsonNode? template in templatesData)
            {
                try
                {
                    if (template is JsonObject templateObj)
                    {
                        templates.Add(new TemplateSearchData(templateObj, logger, additionalDataReaders));
                    }
                    else
                    {
                        throw new Exception($"Unexpected data in template package cache data, property: {nameof(Templates)}.");
                    }
                }
                catch (Exception ex)
                {
                    logger.LogDebug($"Template package {Name}: Failed to read template data {template}, details: {ex}.");
                }
            }
            Templates = templates;
            //read additional data
            AdditionalData = additionalDataReaders != null
                ? TemplateSearchCache.ReadAdditionalData(jObject, additionalDataReaders, logger)
                : new Dictionary<string, object>();
        }

        #region JsonConverter
        private class TemplatePackageSearchDataJsonConverter : System.Text.Json.Serialization.JsonConverter<TemplatePackageSearchData>
        {
            public override TemplatePackageSearchData Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
                => throw new NotImplementedException();

#if NET7_0_OR_GREATER
            [UnconditionalSuppressMessage("AOT", "IL2026:RequiresUnreferencedCode", Justification = "Templates and AdditionalData are serialized with known types.")]
            [UnconditionalSuppressMessage("AOT", "IL3050:RequiresDynamicCode", Justification = "Templates and AdditionalData are serialized with known types.")]
#endif
            public override void Write(Utf8JsonWriter writer, TemplatePackageSearchData value, JsonSerializerOptions options)
            {
                if (value == null)
                {
                    return;
                }
                writer.WriteStartObject();
                writer.WritePropertyName(nameof(Name));
                writer.WriteStringValue(value.Name);
                if (!string.IsNullOrWhiteSpace(value.Version))
                {
                    writer.WritePropertyName(nameof(Version));
                    writer.WriteStringValue(value.Version);
                }
                if (value.TotalDownloads != 0)
                {
                    writer.WritePropertyName(nameof(TotalDownloads));
                    writer.WriteNumberValue(value.TotalDownloads);
                }
                if (value.Owners.Any())
                {
                    writer.WritePropertyName(nameof(Owners));
                    if (value.Owners.Count == 1)
                    {
                        writer.WriteStringValue(value.Owners[0]);
                    }
                    else
                    {
                        writer.WriteStartArray();
                        foreach (string owner in value.Owners)
                        {
                            writer.WriteStringValue(owner);
                        }
                        writer.WriteEndArray();
                    }
                }

                if (value.Reserved)
                {
                    writer.WritePropertyName(nameof(Reserved));
                    writer.WriteBooleanValue(value.Reserved);
                }
                if (!string.IsNullOrWhiteSpace(value.Description))
                {
                    writer.WritePropertyName(nameof(Description));
                    writer.WriteStringValue(value.Description);
                }
                if (!string.IsNullOrWhiteSpace(value.IconUrl))
                {
                    writer.WritePropertyName(nameof(IconUrl));
                    writer.WriteStringValue(value.IconUrl);
                }

                writer.WritePropertyName(nameof(Templates));
                JsonSerializer.Serialize(writer, value.Templates, options);

                if (value.AdditionalData.Any())
                {
                    foreach (var item in value.AdditionalData)
                    {
                        writer.WritePropertyName(item.Key);
                        JsonSerializer.Serialize(writer, item.Value, options);
                    }
                }
                writer.WriteEndObject();
            }
        }

        #endregion
    }
}