< Summary

Class:Azure.Core.Serialization.JsonObjectSerializer
Assembly:Azure.Core
File(s):C:\Git\azure-sdk-for-net\sdk\core\Azure.Core\src\Serialization\JsonObjectSerializer.cs
Covered lines:62
Uncovered lines:2
Coverable lines:64
Total lines:137
Line coverage:96.8% (62 of 64)
Covered branches:8
Total branches:10
Branch coverage:80% (8 of 10)

Metrics

MethodCyclomatic complexity Line coverage Branch coverage
.ctor()-100%100%
.ctor(...)-100%100%
Serialize(...)-100%100%
SerializeAsync()-100%100%
Deserialize(...)-100%100%
DeserializeAsync()-100%100%
Azure.Core.Serialization.IMemberNameConverter.ConvertMemberName(...)-94.87%100%
GetPropertyName(...)-100%75%

File(s)

C:\Git\azure-sdk-for-net\sdk\core\Azure.Core\src\Serialization\JsonObjectSerializer.cs

#LineLine coverage
 1// Copyright (c) Microsoft Corporation. All rights reserved.
 2// Licensed under the MIT License.
 3
 4using System;
 5using System.Collections.Concurrent;
 6using System.IO;
 7using System.Reflection;
 8using System.Text.Json;
 9using System.Text.Json.Serialization;
 10using System.Threading;
 11using System.Threading.Tasks;
 12
 13namespace Azure.Core.Serialization
 14{
 15    /// <summary>
 16    /// A <see cref="JsonObjectSerializer"/> implementation that uses <see cref="JsonSerializer"/> to for serialization/
 17    /// </summary>
 18    public class JsonObjectSerializer : ObjectSerializer, IMemberNameConverter
 19    {
 20        private readonly ConcurrentDictionary<MemberInfo, string?> _cache;
 21        private readonly JsonSerializerOptions _options;
 22
 23        /// <summary>
 24        /// Initializes new instance of <see cref="JsonObjectSerializer"/>.
 25        /// </summary>
 6826        public JsonObjectSerializer() : this(new JsonSerializerOptions())
 27        {
 6828        }
 29
 30        /// <summary>
 31        /// Initializes new instance of <see cref="JsonObjectSerializer"/>.
 32        /// </summary>
 33        /// <param name="options">The <see cref="JsonSerializerOptions"/> instance to use when serializing/deserializing
 34        /// <exception cref="ArgumentNullException"><paramref name="options"/> is null.</exception>
 7635        public JsonObjectSerializer(JsonSerializerOptions options)
 36        {
 7637            _options = options ?? throw new ArgumentNullException(nameof(options));
 38
 39            // TODO: Consider using WeakReference cache to allow the GC to collect if the JsonObjectSerialized is held f
 7240            _cache = new ConcurrentDictionary<MemberInfo, string?>();
 7241        }
 42
 43        /// <inheritdoc />
 44        public override void Serialize(Stream stream, object? value, Type inputType, CancellationToken cancellationToken
 45        {
 1246            var buffer = JsonSerializer.SerializeToUtf8Bytes(value, inputType, _options);
 1247            stream.Write(buffer, 0, buffer.Length);
 1248        }
 49
 50        /// <inheritdoc />
 51        public override async ValueTask SerializeAsync(Stream stream, object? value, Type inputType, CancellationToken c
 52        {
 1053            await JsonSerializer.SerializeAsync(stream, value, inputType, _options, cancellationToken).ConfigureAwait(fa
 1054        }
 55
 56        /// <inheritdoc />
 57        public override object Deserialize(Stream stream, Type returnType, CancellationToken cancellationToken)
 58        {
 5659            using var memoryStream = new MemoryStream();
 5660            stream.CopyTo(memoryStream);
 5661            return JsonSerializer.Deserialize(memoryStream.ToArray(), returnType, _options);
 5262        }
 63
 64        /// <inheritdoc />
 65        public override async ValueTask<object> DeserializeAsync(Stream stream, Type returnType, CancellationToken cance
 66        {
 5667            return await JsonSerializer.DeserializeAsync(stream, returnType, _options, cancellationToken).ConfigureAwait
 5268        }
 69
 70        /// <inheritdoc/>
 71        string? IMemberNameConverter.ConvertMemberName(MemberInfo member)
 72        {
 3273            Argument.AssertNotNull(member, nameof(member));
 74
 3275            return _cache.GetOrAdd(member, m =>
 3276            {
 3277                // Mimics property enumeration based on:
 3278                // * https://github.com/dotnet/corefx/blob/v3.1.0/src/System.Text.Json/src/System/Text/Json/Serializatio
 3279                // * TODO: Add support for fields when .NET 5 GAs (https://github.com/Azure/azure-sdk-for-net/issues/136
 3280
 6481                if (m is PropertyInfo propertyInfo)
 3282                {
 3283                    // Ignore indexers.
 5284                    if (propertyInfo.GetIndexParameters().Length > 0)
 3285                    {
 086                        return null;
 3287                    }
 3288
 3289                    // Only support public getters and/or setters.
 5290                    if (propertyInfo.GetMethod?.IsPublic == true ||
 5291                        propertyInfo.SetMethod?.IsPublic == true)
 3292                    {
 4893                        if (propertyInfo.GetCustomAttribute<JsonIgnoreAttribute>() != null)
 3294                        {
 3695                            return null;
 3296                        }
 3297
 3298                        // Ignore - but do not assert correctness - for JsonExtensionDataAttribute based on
 3299                        // https://github.com/dotnet/corefx/blob/v3.1.0/src/System.Text.Json/src/System/Text/Json/Serial
 44100                        if (propertyInfo.GetCustomAttribute<JsonExtensionDataAttribute>() != null)
 32101                        {
 0102                            return null;
 32103                        }
 32104
 32105                        // No need to validate collisions since they are based on the serialized name.
 44106                        return GetPropertyName(propertyInfo);
 32107                    }
 32108                }
 32109
 32110                // The member is unsupported or ignored.
 48111                return null;
 32112            });
 113        }
 114
 115        private string GetPropertyName(MemberInfo memberInfo)
 116        {
 117            // Mimics property name determination based on
 118            // https://github.com/dotnet/runtime/blob/dc8b6f90/src/libraries/System.Text.Json/src/System/Text/Json/Seria
 119
 12120            JsonPropertyNameAttribute nameAttribute = memberInfo.GetCustomAttribute<JsonPropertyNameAttribute>(false);
 12121            if (nameAttribute != null)
 122            {
 4123                return nameAttribute.Name
 4124                    ?? throw new InvalidOperationException($"The JSON property name for '{memberInfo.DeclaringType}.{mem
 125            }
 8126            else if (_options.PropertyNamingPolicy != null)
 127            {
 4128                return _options.PropertyNamingPolicy.ConvertName(memberInfo.Name)
 4129                    ?? throw new InvalidOperationException($"The JSON property name for '{memberInfo.DeclaringType}.{mem
 130            }
 131            else
 132            {
 4133                return memberInfo.Name;
 134            }
 135        }
 136    }
 137}