< Summary

Class:Microsoft.Azure.Search.Serialization.JsonUtility
Assembly:Microsoft.Azure.Search.Data
File(s):C:\Git\azure-sdk-for-net\sdk\search\Microsoft.Azure.Search.Data\src\Customizations\Serialization\JsonUtility.cs
Covered lines:65
Uncovered lines:0
Coverable lines:65
Total lines:163
Line coverage:100% (65 of 65)
Covered branches:10
Total branches:12
Branch coverage:83.3% (10 of 12)

Metrics

MethodCyclomatic complexity Line coverage Branch coverage
get_CamelCaseResolver()-100%100%
get_DefaultResolver()-100%100%
CreateTypedSerializerSettings(...)-100%100%
CreateTypedDeserializerSettings(...)-100%100%
CreateDocumentSerializerSettings(...)-100%100%
CreateDocumentDeserializerSettings(...)-100%100%
CreateSerializerSettings(...)-100%100%
CreateDeserializerSettings(...)-100%100%
CopySettings(...)-100%100%
.ctor()-100%100%
get_Instance()-100%100%
Copy(...)-100%100%
MakeCopyExpr(...)-100%100%
CopyAllProperties()-100%66.67%
IsPropertyDeprecated(...)-100%100%

File(s)

C:\Git\azure-sdk-for-net\sdk\search\Microsoft.Azure.Search.Data\src\Customizations\Serialization\JsonUtility.cs

#LineLine coverage
 1// Copyright (c) Microsoft Corporation. All rights reserved.
 2// Licensed under the MIT License. See License.txt in the project root for
 3// license information.
 4
 5using System;
 6using System.Collections.Generic;
 7using System.Linq;
 8using System.Linq.Expressions;
 9using System.Reflection;
 10using Microsoft.Azure.Search.Models;
 11using Microsoft.Azure.Search.Serialization.Internal;
 12using Microsoft.Rest.Serialization;
 13using Newtonsoft.Json;
 14using Newtonsoft.Json.Serialization;
 15using static System.Linq.Expressions.Expression;
 16using Throw = Microsoft.Azure.Search.Common.Throw;
 17
 18namespace Microsoft.Azure.Search.Serialization
 19{
 20    internal static class JsonUtility
 21    {
 34622        private static IContractResolver CamelCaseResolver { get; } = new CamelCasePropertyNamesContractResolver();
 23
 40224        private static IContractResolver DefaultResolver { get; } = new DefaultContractResolver();
 25
 26        public static JsonSerializerSettings CreateTypedSerializerSettings<T>(JsonSerializerSettings baseSettings, bool 
 40627            CreateSerializerSettings<T>(baseSettings, useCamelCase);
 28
 29        public static JsonSerializerSettings CreateTypedDeserializerSettings<T>(JsonSerializerSettings baseSettings) =>
 23430            CreateDeserializerSettings<T>(baseSettings);
 31
 32        public static JsonSerializerSettings CreateDocumentSerializerSettings(JsonSerializerSettings baseSettings) =>
 4033            CreateSerializerSettings<Document>(baseSettings, useCamelCase: false);
 34
 35        public static JsonSerializerSettings CreateDocumentDeserializerSettings(JsonSerializerSettings baseSettings) =>
 9236            CreateDeserializerSettings<Document>(baseSettings);
 37
 38        private static JsonSerializerSettings CreateSerializerSettings<T>(
 39            JsonSerializerSettings baseSettings,
 40            bool useCamelCase)
 41        {
 44642            JsonSerializerSettings settings = CopySettings(baseSettings);
 44643            settings.Converters.Add(new GeoJsonPointConverter());
 44644            settings.Converters.Add(new IndexActionConverter<T>());
 44645            settings.Converters.Add(new Iso8601DateTimeConverter());
 44646            settings.Converters.Add(new EdmDoubleConverter());
 44647            settings.NullValueHandling = NullValueHandling.Ignore;
 48
 44649            if (useCamelCase)
 50            {
 34451                settings.ContractResolver = CamelCaseResolver;
 52            }
 10253            else if (settings.ContractResolver is ReadOnlyJsonContractResolver)
 54            {
 9055                settings.ContractResolver = DefaultResolver;
 56            }
 57
 44658            return settings;
 59        }
 60
 61        private static JsonSerializerSettings CreateDeserializerSettings<T>(JsonSerializerSettings baseSettings)
 62        {
 32663            JsonSerializerSettings settings = CopySettings(baseSettings);
 32664            settings.Converters.Add(new GeoJsonPointConverter());
 32665            settings.Converters.Add(new DocumentConverter());
 32666            settings.Converters.Add(new Iso8601DateTimeConverter());
 32667            settings.Converters.Add(new EdmDoubleConverter());
 32668            settings.Converters.Add(new SearchResultConverter<T>());
 32669            settings.Converters.Add(new SuggestResultConverter<T>());
 32670            settings.DateParseHandling = DateParseHandling.DateTimeOffset;
 71
 72            // Fail when deserializing null into a non-nullable type. This is to avoid silent data corruption issues.
 32673            settings.NullValueHandling = NullValueHandling.Include;
 74
 32675            if (settings.ContractResolver is ReadOnlyJsonContractResolver)
 76            {
 31077                settings.ContractResolver = DefaultResolver;
 78            }
 79
 32680            return settings;
 81        }
 82
 83        private static JsonSerializerSettings CopySettings(JsonSerializerSettings baseSettings) =>
 77284            JsonSerializerSettingsCopier.Instance.Copy(baseSettings);
 85
 86        // Unfortunately we can't just assign the properties of JsonSerializerSettings between instances,
 87        // because some of these properties come and go within the span of a few JSON.NET versions, and the
 88        // Azure .NET SDKs can reference a very wide range of possible versions. Instead, we use reflection
 89        // and dynamic compilation to create a copy method tailored to whatever version of JSON.NET we find
 90        // ourselves using.
 91        private class JsonSerializerSettingsCopier
 92        {
 93            private readonly Delegate _copy;
 94
 295            private JsonSerializerSettingsCopier()
 96            {
 97                Type sourceType, targetType;
 298                sourceType = targetType = typeof(JsonSerializerSettings);
 99
 2100                ParameterExpression source = Parameter(sourceType);
 2101                Expression copyExpr = MakeCopyExpr(source);
 102
 103                // Emits 'source => {copyExpr}' where copyExpr refers to source and returns a copy of it.
 2104                LambdaExpression lambdaExpression =
 2105                    Lambda(
 2106                        delegateType: GetFuncType(sourceType, targetType),
 2107                        body: copyExpr,
 2108                        parameters: source);
 109
 2110                _copy = lambdaExpression.Compile();
 2111            }
 112
 774113            public static JsonSerializerSettingsCopier Instance { get; } = new JsonSerializerSettingsCopier();
 114
 115            public JsonSerializerSettings Copy(JsonSerializerSettings source)
 116            {
 772117                Throw.IfArgumentNull(source, nameof(source));
 118
 119                // Shallow copy all the properties first, then deep copy Converters.
 772120                var newSettings = (JsonSerializerSettings)_copy.DynamicInvoke(source);
 772121                newSettings.Converters = new List<JsonConverter>(source.Converters);
 772122                return newSettings;
 123            }
 124
 125            private static Expression MakeCopyExpr(ParameterExpression sourceExpr)
 126            {
 2127                ParameterExpression source = Variable(typeof(JsonSerializerSettings));
 2128                ParameterExpression target = Variable(typeof(JsonSerializerSettings));
 129
 2130                Expression assignSource = Assign(left: source, right: sourceExpr);
 2131                Expression assignTarget = Assign(left: target, right: New(typeof(JsonSerializerSettings)));
 132
 2133                IEnumerable<Expression> copy = CopyAllProperties(source, target);
 134
 2135                return Block(
 2136                    type: typeof(JsonSerializerSettings),
 2137                    variables: new[] { source, target },
 2138                    expressions: new[] { assignSource, assignTarget }.Concat(copy));
 139            }
 140
 141            private static IEnumerable<Expression> CopyAllProperties(
 142                ParameterExpression source,
 143                ParameterExpression target)
 144            {
 2145                var settableNonDeprecatedProperties =
 2146                    typeof(JsonSerializerSettings).GetTypeInfo().DeclaredProperties
 66147                    .Where(p => p.CanRead && p.CanWrite && !IsPropertyDeprecated(p));
 148
 120149                foreach (PropertyInfo property in settableNonDeprecatedProperties)
 150                {
 58151                    yield return Assign(
 58152                        left: PropertyOrField(target, property.Name),
 58153                        right: PropertyOrField(source, property.Name));
 154                }
 155
 2156                yield return target;
 2157            }
 158
 159            private static bool IsPropertyDeprecated(PropertyInfo property) =>
 70160                property.GetCustomAttributes().Any(a => a is ObsoleteAttribute);
 161        }
 162    }
 163}