diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ValueConverters/AbpJsonValueConverter.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ValueConverters/AbpJsonValueConverter.cs index 7378ab8eff..1718ba6419 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ValueConverters/AbpJsonValueConverter.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ValueConverters/AbpJsonValueConverter.cs @@ -19,11 +19,17 @@ namespace Volo.Abp.EntityFrameworkCore.ValueConverters return JsonSerializer.Serialize(d); } + private static readonly JsonSerializerOptions DeserializeOptions = new JsonSerializerOptions() + { + Converters = + { + new ObjectToInferredTypesConverter() + } + }; + private static TPropertyType DeserializeObject(string s) { - var deserializeOptions = new JsonSerializerOptions(); - deserializeOptions.Converters.Add(new ObjectToInferredTypesConverter()); - return JsonSerializer.Deserialize(s, deserializeOptions); + return JsonSerializer.Deserialize(s, DeserializeOptions); } } } diff --git a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ValueConverters/ExtraPropertiesValueConverter.cs b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ValueConverters/ExtraPropertiesValueConverter.cs index 2949437ad0..fd8ab43fd0 100644 --- a/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ValueConverters/ExtraPropertiesValueConverter.cs +++ b/framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ValueConverters/ExtraPropertiesValueConverter.cs @@ -41,17 +41,22 @@ namespace Volo.Abp.EntityFrameworkCore.ValueConverters return JsonSerializer.Serialize(copyDictionary); } + private static readonly JsonSerializerOptions DeserializeOptions = new JsonSerializerOptions() + { + Converters = + { + new ObjectToInferredTypesConverter() + } + }; + private static ExtraPropertyDictionary DeserializeObject(string extraPropertiesAsJson, Type entityType) { if (extraPropertiesAsJson.IsNullOrEmpty() || extraPropertiesAsJson == "{}") { return new ExtraPropertyDictionary(); } - - var deserializeOptions = new JsonSerializerOptions(); - deserializeOptions.Converters.Add(new ObjectToInferredTypesConverter()); - - var dictionary = JsonSerializer.Deserialize(extraPropertiesAsJson, deserializeOptions) ?? + + var dictionary = JsonSerializer.Deserialize(extraPropertiesAsJson, DeserializeOptions) ?? new ExtraPropertyDictionary(); if (entityType != null) diff --git a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/ApiDescriptionFinder.cs b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/ApiDescriptionFinder.cs index cce91cb5d7..a70327b8e6 100644 --- a/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/ApiDescriptionFinder.cs +++ b/framework/src/Volo.Abp.Http.Client/Volo/Abp/Http/Client/DynamicProxying/ApiDescriptionFinder.cs @@ -90,6 +90,11 @@ namespace Volo.Abp.Http.Client.DynamicProxying return await Cache.GetAsync(baseUrl, () => GetApiDescriptionFromServerAsync(client, baseUrl)); } + private static readonly JsonSerializerOptions DeserializeOptions = new JsonSerializerOptions + { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase + }; + protected virtual async Task GetApiDescriptionFromServerAsync( HttpClient client, string baseUrl) @@ -113,10 +118,7 @@ namespace Volo.Abp.Http.Client.DynamicProxying var content = await response.Content.ReadAsStringAsync(); - var result = JsonSerializer.Deserialize(content, new JsonSerializerOptions - { - PropertyNamingPolicy = JsonNamingPolicy.CamelCase - }); + var result = JsonSerializer.Deserialize(content, DeserializeOptions); return result; } diff --git a/framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/AbpSystemTextJsonSerializerProvider.cs b/framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/AbpSystemTextJsonSerializerProvider.cs index 570d1c162c..217f40386a 100644 --- a/framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/AbpSystemTextJsonSerializerProvider.cs +++ b/framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/AbpSystemTextJsonSerializerProvider.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Concurrent; using System.Text.Json; using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; @@ -39,21 +40,26 @@ namespace Volo.Abp.Json.SystemTextJson return JsonSerializer.Deserialize(jsonString, type, CreateJsonSerializerOptions(camelCase)); } + private readonly ConcurrentDictionary JsonSerializerOptionsCache = new ConcurrentDictionary(); + protected virtual JsonSerializerOptions CreateJsonSerializerOptions(bool camelCase = true, bool indented = false) { - var settings = new JsonSerializerOptions(Options.JsonSerializerOptions); - - if (camelCase) + return JsonSerializerOptionsCache.GetOrAdd($"default{camelCase}{indented}", _ => { - settings.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; - } + var settings = new JsonSerializerOptions(Options.JsonSerializerOptions); - if (indented) - { - settings.WriteIndented = true; - } + if (camelCase) + { + settings.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; + } + + if (indented) + { + settings.WriteIndented = true; + } - return settings; + return settings; + }); } } } diff --git a/framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpHasExtraPropertiesJsonConverter.cs b/framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpHasExtraPropertiesJsonConverter.cs index 0d75a04eed..5b2eb5a15a 100644 --- a/framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpHasExtraPropertiesJsonConverter.cs +++ b/framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpHasExtraPropertiesJsonConverter.cs @@ -17,13 +17,18 @@ namespace Volo.Abp.Json.SystemTextJson.JsonConverters { _readJsonSerializerOptions ??= JsonSerializerOptionsHelper.Create(options, x => x == this); - var converterFactory = _readJsonSerializerOptions.Converters.FirstOrDefault(x => x is AbpHasExtraPropertiesJsonConverterFactory); - converterFactory?.As().AddExcludeTypes(typeToConvert); - var rootElement = JsonDocument.ParseValue(ref reader).RootElement; if (rootElement.ValueKind == JsonValueKind.Object) { - var extensibleObject = rootElement.Deserialize(_readJsonSerializerOptions); + var converterFactory = _readJsonSerializerOptions.Converters + .FirstOrDefault(x => x is AbpHasExtraPropertiesJsonConverterFactory) + .As(); + + T extensibleObject; + using (converterFactory != null ? converterFactory.Exclude(typeToConvert) : NullDisposable.Instance) + { + extensibleObject = rootElement.Deserialize(_readJsonSerializerOptions); + } var extraPropertiesJsonProperty = rootElement.EnumerateObject().FirstOrDefault(x => x.Name.Equals(nameof(IHasExtraProperties.ExtraProperties), StringComparison.OrdinalIgnoreCase)); diff --git a/framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpHasExtraPropertiesJsonConverterFactory.cs b/framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpHasExtraPropertiesJsonConverterFactory.cs index dfe95b85c9..e0d99bf8cb 100644 --- a/framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpHasExtraPropertiesJsonConverterFactory.cs +++ b/framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpHasExtraPropertiesJsonConverterFactory.cs @@ -1,10 +1,11 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; -using System.Collections.Immutable; +using System.Linq; using System.Reflection; using System.Text.Json; using System.Text.Json.Serialization; +using System.Threading; using Volo.Abp.Data; namespace Volo.Abp.Json.SystemTextJson.JsonConverters @@ -13,17 +14,21 @@ namespace Volo.Abp.Json.SystemTextJson.JsonConverters { private static readonly ConcurrentDictionary CachedTypes = new ConcurrentDictionary(); - private readonly List _excludeTypes = new List(); + private readonly AsyncLocal> _excludeTypes = new AsyncLocal>(); - public virtual AbpHasExtraPropertiesJsonConverterFactory AddExcludeTypes(params Type[] excludeTypes) + public IDisposable Exclude(params Type[] excludeTypes) { - _excludeTypes.AddIfNotContains(excludeTypes); - return this; + var parent = _excludeTypes.Value; + _excludeTypes.Value = excludeTypes.ToList(); + return new DisposeAction(() => + { + _excludeTypes.Value = parent; + }); } - + public override bool CanConvert(Type typeToConvert) { - if (_excludeTypes.Contains(typeToConvert)) + if (_excludeTypes.Value != null && _excludeTypes.Value.Contains(typeToConvert)) { return false; } diff --git a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Json/JsonLocalizationDictionaryBuilder.cs b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Json/JsonLocalizationDictionaryBuilder.cs index 9ccc6738a6..79a8cb0ac4 100644 --- a/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Json/JsonLocalizationDictionaryBuilder.cs +++ b/framework/src/Volo.Abp.Localization/Volo/Abp/Localization/Json/JsonLocalizationDictionaryBuilder.cs @@ -24,6 +24,14 @@ namespace Volo.Abp.Localization.Json } } + private static readonly JsonSerializerOptions DeserializeOptions = new JsonSerializerOptions + { + PropertyNameCaseInsensitive = true, + DictionaryKeyPolicy = JsonNamingPolicy.CamelCase, + ReadCommentHandling = JsonCommentHandling.Skip, + AllowTrailingCommas = true + }; + /// /// Builds an from given json string. /// @@ -33,15 +41,7 @@ namespace Volo.Abp.Localization.Json JsonLocalizationFile jsonFile; try { - var options = new JsonSerializerOptions - { - PropertyNameCaseInsensitive = true, - DictionaryKeyPolicy = JsonNamingPolicy.CamelCase, - ReadCommentHandling = JsonCommentHandling.Skip, - AllowTrailingCommas = true - }; - - jsonFile = JsonSerializer.Deserialize(jsonString, options); + jsonFile = JsonSerializer.Deserialize(jsonString, DeserializeOptions); } catch (JsonException ex) {