diff --git a/framework/Volo.Abp.sln b/framework/Volo.Abp.sln index fb59c91051..6957eb2baf 100644 --- a/framework/Volo.Abp.sln +++ b/framework/Volo.Abp.sln @@ -355,7 +355,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.AspNetCore.Compone EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Swashbuckle", "src\Volo.Abp.Swashbuckle\Volo.Abp.Swashbuckle.csproj", "{DD9519E0-5A68-48DC-A051-7BF2AC922F3E}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Json.Newtonsoft", "src\Volo.Abp.Json.Newtonsoft\Volo.Abp.Json.Newtonsoft.csproj", "{B5DEA857-1A22-4479-8441-E871D1BCBAB2}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Json.Tests", "test\Volo.Abp.Json.Tests\Volo.Abp.Json.Tests.csproj", "{00D07595-993C-40FC-BD90-0DD6331414D3}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -1059,10 +1059,10 @@ Global {DD9519E0-5A68-48DC-A051-7BF2AC922F3E}.Debug|Any CPU.Build.0 = Debug|Any CPU {DD9519E0-5A68-48DC-A051-7BF2AC922F3E}.Release|Any CPU.ActiveCfg = Release|Any CPU {DD9519E0-5A68-48DC-A051-7BF2AC922F3E}.Release|Any CPU.Build.0 = Release|Any CPU - {B5DEA857-1A22-4479-8441-E871D1BCBAB2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B5DEA857-1A22-4479-8441-E871D1BCBAB2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B5DEA857-1A22-4479-8441-E871D1BCBAB2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B5DEA857-1A22-4479-8441-E871D1BCBAB2}.Release|Any CPU.Build.0 = Release|Any CPU + {00D07595-993C-40FC-BD90-0DD6331414D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {00D07595-993C-40FC-BD90-0DD6331414D3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {00D07595-993C-40FC-BD90-0DD6331414D3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {00D07595-993C-40FC-BD90-0DD6331414D3}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1242,7 +1242,7 @@ Global {B9D1ADCB-D552-4626-A1F1-78FF72C1E822} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {89840441-5A3A-4FD7-9CB4-E5B52FAEF72A} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} {DD9519E0-5A68-48DC-A051-7BF2AC922F3E} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} - {B5DEA857-1A22-4479-8441-E871D1BCBAB2} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6} + {00D07595-993C-40FC-BD90-0DD6331414D3} = {447C8A77-E5F0-4538-8687-7383196D04EA} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj index fff97c83c3..a018dbbffd 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj @@ -28,6 +28,7 @@ + diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs index 11a6ae9442..61d73cb48b 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs @@ -136,7 +136,7 @@ namespace Volo.Abp.AspNetCore.Mvc }) .AddViewLocalization(); //TODO: How to configure from the application? Also, consider to move to a UI module since APIs does not care about it. - context.Services.TryAddEnumerable(ServiceDescriptor.Transient, AbpJsonOptionsSetup>()); + mvcCoreBuilder.AddAbpHybridJson(); Configure(options => { diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpHybridJsonInputFormatter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpHybridJsonInputFormatter.cs new file mode 100644 index 0000000000..4ad90bcad2 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpHybridJsonInputFormatter.cs @@ -0,0 +1,38 @@ +using System.Text; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc.Formatters; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Json.SystemTextJson; + +namespace Volo.Abp.AspNetCore.Mvc.Json +{ + public class AbpHybridJsonInputFormatter : TextInputFormatter, IInputFormatterExceptionPolicy + { + public AbpHybridJsonInputFormatter() + { + SupportedEncodings.Add(UTF8EncodingWithoutBOM); + SupportedEncodings.Add(UTF16EncodingLittleEndian); + + SupportedMediaTypes.Add(MediaTypeHeaderValues.ApplicationJson); + SupportedMediaTypes.Add(MediaTypeHeaderValues.TextJson); + SupportedMediaTypes.Add(MediaTypeHeaderValues.ApplicationAnyJsonSyntax); + } + + public async override Task ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding) + { + return await GetTextInputFormatter(context).ReadRequestBodyAsync(context, encoding); + } + + private TextInputFormatter GetTextInputFormatter(InputFormatterContext context) + { + if (context.HttpContext.RequestServices.GetRequiredService().CanHandle(context.ModelType)) + { + return context.HttpContext.RequestServices.GetRequiredService(); + } + + return context.HttpContext.RequestServices.GetRequiredService(); + } + + public InputFormatterExceptionPolicy ExceptionPolicy => InputFormatterExceptionPolicy.MalformedInputExceptions; + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpHybridJsonOutputFormatter.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpHybridJsonOutputFormatter.cs new file mode 100644 index 0000000000..7cf991be96 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpHybridJsonOutputFormatter.cs @@ -0,0 +1,35 @@ +using System.Text; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc.Formatters; +using Microsoft.Extensions.DependencyInjection; +using Volo.Abp.Json.SystemTextJson; + +namespace Volo.Abp.AspNetCore.Mvc.Json +{ + public class AbpHybridJsonOutputFormatter : TextOutputFormatter + { + public AbpHybridJsonOutputFormatter() + { + SupportedEncodings.Add(Encoding.UTF8); + SupportedEncodings.Add(Encoding.Unicode); + SupportedMediaTypes.Add(MediaTypeHeaderValues.ApplicationJson); + SupportedMediaTypes.Add(MediaTypeHeaderValues.TextJson); + SupportedMediaTypes.Add(MediaTypeHeaderValues.ApplicationAnyJsonSyntax); + } + + public async override Task WriteResponseBodyAsync(OutputFormatterWriteContext context, Encoding selectedEncoding) + { + await GetTextInputFormatter(context).WriteResponseBodyAsync(context, selectedEncoding); + } + + private TextOutputFormatter GetTextInputFormatter(OutputFormatterWriteContext context) + { + if (context.HttpContext.RequestServices.GetRequiredService().CanHandle(context.ObjectType)) + { + return context.HttpContext.RequestServices.GetRequiredService(); + } + + return context.HttpContext.RequestServices.GetRequiredService(); + } + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpJsonOptionsSetup.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpJsonOptionsSetup.cs index 821b2c9218..b456204ed8 100644 --- a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpJsonOptionsSetup.cs +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpJsonOptionsSetup.cs @@ -2,8 +2,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; -using Volo.Abp.Json.JsonConverters; -using Volo.Abp.Json; +using Volo.Abp.Json.SystemTextJson.JsonConverters; namespace Volo.Abp.AspNetCore.Mvc.Json { diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpMvcJsonContractResolver.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpMvcJsonContractResolver.cs new file mode 100644 index 0000000000..2db8bc3f06 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpMvcJsonContractResolver.cs @@ -0,0 +1,45 @@ +using System; +using System.Reflection; +using Newtonsoft.Json; +using Newtonsoft.Json.Serialization; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Json.Newtonsoft; +using Volo.Abp.Reflection; +using Volo.Abp.Timing; + +namespace Volo.Abp.AspNetCore.Mvc.Json +{ + public class AbpMvcJsonContractResolver : DefaultContractResolver, ITransientDependency + { + private readonly AbpJsonIsoDateTimeConverter _dateTimeConverter; + + public AbpMvcJsonContractResolver(AbpJsonIsoDateTimeConverter dateTimeConverter) + { + _dateTimeConverter = dateTimeConverter; + + NamingStrategy = new CamelCaseNamingStrategy(); + } + + protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) + { + var property = base.CreateProperty(member, memberSerialization); + + ModifyProperty(member, property); + + return property; + } + + protected virtual void ModifyProperty(MemberInfo member, JsonProperty property) + { + if (property.PropertyType != typeof(DateTime) && property.PropertyType != typeof(DateTime?)) + { + return; + } + + if (ReflectionHelper.GetSingleAttributeOfMemberOrDeclaringTypeOrDefault(member) == null) + { + property.Converter = _dateTimeConverter; + } + } + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpMvcNewtonsoftJsonOptionsSetup.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpMvcNewtonsoftJsonOptionsSetup.cs new file mode 100644 index 0000000000..48a09e2426 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpMvcNewtonsoftJsonOptionsSetup.cs @@ -0,0 +1,22 @@ +using System; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; + +namespace Volo.Abp.AspNetCore.Mvc.Json +{ + public class AbpMvcNewtonsoftJsonOptionsSetup : IConfigureOptions + { + protected IServiceProvider ServiceProvider { get; } + + public AbpMvcNewtonsoftJsonOptionsSetup(IServiceProvider serviceProvider) + { + ServiceProvider = serviceProvider; + } + + public void Configure(MvcNewtonsoftJsonOptions options) + { + options.SerializerSettings.ContractResolver = ServiceProvider.GetRequiredService(); + } + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/MediaTypeHeaderValues.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/MediaTypeHeaderValues.cs new file mode 100644 index 0000000000..d1f1b34b1a --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/MediaTypeHeaderValues.cs @@ -0,0 +1,22 @@ +using Microsoft.Net.Http.Headers; + +namespace Volo.Abp.AspNetCore.Mvc.Json +{ + /// + /// https://github.com/dotnet/aspnetcore/blob/master/src/Mvc/Mvc.NewtonsoftJson/src/MediaTypeHeaderValues.cs + /// + internal static class MediaTypeHeaderValues + { + public static readonly MediaTypeHeaderValue ApplicationJson = MediaTypeHeaderValue.Parse("application/json").CopyAsReadOnly(); + + public static readonly MediaTypeHeaderValue TextJson = MediaTypeHeaderValue.Parse("text/json").CopyAsReadOnly(); + + public static readonly MediaTypeHeaderValue ApplicationAnyJsonSyntax = MediaTypeHeaderValue.Parse("application/*+json").CopyAsReadOnly(); + + public static readonly MediaTypeHeaderValue ApplicationXml = MediaTypeHeaderValue.Parse("application/xml").CopyAsReadOnly(); + + public static readonly MediaTypeHeaderValue TextXml = MediaTypeHeaderValue.Parse("text/xml").CopyAsReadOnly(); + + public static readonly MediaTypeHeaderValue ApplicationAnyXmlSyntax = MediaTypeHeaderValue.Parse("application/*+xml").CopyAsReadOnly(); + } +} diff --git a/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/MvcCoreBuilderExtensions.cs b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/MvcCoreBuilderExtensions.cs new file mode 100644 index 0000000000..9eaa0c826a --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/MvcCoreBuilderExtensions.cs @@ -0,0 +1,82 @@ +using System.Buffers; +using System.Text.Json; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Formatters; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Extensions.Options; +using System.Text.Encodings.Web; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.ObjectPool; + +namespace Volo.Abp.AspNetCore.Mvc.Json +{ + public static class MvcCoreBuilderExtensions + { + public static IMvcCoreBuilder AddAbpHybridJson(this IMvcCoreBuilder builder) + { + //SystemTextJsonInputFormatter + builder.Services.AddTransient(provider => + { + var jsonOptions = provider.GetRequiredService>(); + var logger = provider.GetRequiredService().CreateLogger(); + return new SystemTextJsonInputFormatter(jsonOptions.Value, logger); + }); + + //NewtonsoftJsonInputFormatter + builder.Services.AddTransient(provider => + { + var jsonOptions = provider.GetRequiredService>().Value; + + return new NewtonsoftJsonInputFormatter( + provider.GetRequiredService().CreateLogger(), + jsonOptions.SerializerSettings, + provider.GetRequiredService>(), + provider.GetRequiredService(), + provider.GetRequiredService>().Value, + jsonOptions); + }); + + //SystemTextJsonOutputFormatter + builder.Services.AddTransient(provider => + { + var jsonSerializerOptions = provider.GetRequiredService>().Value.JsonSerializerOptions; + if (jsonSerializerOptions.Encoder is null) + { + // If the user hasn't explicitly configured the encoder, use the less strict encoder that does not encode all non-ASCII characters. + jsonSerializerOptions = new JsonSerializerOptions(jsonSerializerOptions) + { + Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, + }; + } + return new SystemTextJsonOutputFormatter(jsonSerializerOptions); + }); + + //NewtonsoftJsonOutputFormatter + builder.Services.AddTransient(provider => + { + var jsonOptions = provider.GetRequiredService>().Value; + return new NewtonsoftJsonOutputFormatter( + jsonOptions.SerializerSettings, + provider.GetRequiredService>(), + provider.GetRequiredService>().Value); + }); + + builder.Services.TryAddEnumerable(ServiceDescriptor.Transient, AbpJsonOptionsSetup>()); + builder.Services.TryAddEnumerable(ServiceDescriptor.Transient, AbpMvcNewtonsoftJsonOptionsSetup>()); + + builder.Services.Configure(options => + { + options.InputFormatters.RemoveType(); + options.InputFormatters.RemoveType(); + options.InputFormatters.Add(new AbpHybridJsonInputFormatter()); + + options.OutputFormatters.RemoveType(); + options.OutputFormatters.RemoveType(); + options.OutputFormatters.Add(new AbpHybridJsonOutputFormatter()); + }); + + return builder; + } + } +} 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 afce924d59..7378ab8eff 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 @@ -1,6 +1,6 @@ using System.Text.Json; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Volo.Abp.Json.JsonConverters; +using Volo.Abp.Json.SystemTextJson.JsonConverters; namespace Volo.Abp.EntityFrameworkCore.ValueConverters { 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 00ce8459a6..661da95a19 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 @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Text.Json; using Microsoft.EntityFrameworkCore.Storage.ValueConversion; -using Volo.Abp.Json.JsonConverters; +using Volo.Abp.Json.SystemTextJson.JsonConverters; using Volo.Abp.ObjectExtending; namespace Volo.Abp.EntityFrameworkCore.ValueConverters diff --git a/framework/src/Volo.Abp.Json.Newtonsoft/FodyWeavers.xml b/framework/src/Volo.Abp.Json.Newtonsoft/FodyWeavers.xml deleted file mode 100644 index bc5a74a236..0000000000 --- a/framework/src/Volo.Abp.Json.Newtonsoft/FodyWeavers.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/framework/src/Volo.Abp.Json.Newtonsoft/FodyWeavers.xsd b/framework/src/Volo.Abp.Json.Newtonsoft/FodyWeavers.xsd deleted file mode 100644 index 3f3946e282..0000000000 --- a/framework/src/Volo.Abp.Json.Newtonsoft/FodyWeavers.xsd +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. - - - - - A comma-separated list of error codes that can be safely ignored in assembly verification. - - - - - 'false' to turn off automatic generation of the XML Schema file. - - - - - \ No newline at end of file diff --git a/framework/src/Volo.Abp.Json.Newtonsoft/Volo.Abp.Json.Newtonsoft.csproj b/framework/src/Volo.Abp.Json.Newtonsoft/Volo.Abp.Json.Newtonsoft.csproj deleted file mode 100644 index dd6cdc06ae..0000000000 --- a/framework/src/Volo.Abp.Json.Newtonsoft/Volo.Abp.Json.Newtonsoft.csproj +++ /dev/null @@ -1,25 +0,0 @@ - - - - - - - netstandard2.0 - Volo.Abp.Json.Newtonsoft - Volo.Abp.Json.Newtonsoft - $(AssetTargetFallback);portable-net45+win8+wp8+wpa81; - false - false - false - - - - - - - - - - - - diff --git a/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/AbpJsonModule.cs b/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/AbpJsonModule.cs deleted file mode 100644 index b040f1afbb..0000000000 --- a/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/AbpJsonModule.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.Extensions.Options; -using Volo.Abp.Json; -using Volo.Abp.Json.Newtonsoft; -using Volo.Abp.Modularity; - -namespace Volo.Abp.Json -{ - [DependsOn(typeof(AbpJsonModule))] - public class AbpJsonNewtonsoftModule : AbpModule - { - public override void ConfigureServices(ServiceConfigurationContext context) - { - Configure(options => - { - options.Converters.Add(); - }); - } - } -} diff --git a/framework/src/Volo.Abp.Json/Volo.Abp.Json.csproj b/framework/src/Volo.Abp.Json/Volo.Abp.Json.csproj index ddf8cfba65..1ef71853fa 100644 --- a/framework/src/Volo.Abp.Json/Volo.Abp.Json.csproj +++ b/framework/src/Volo.Abp.Json/Volo.Abp.Json.csproj @@ -16,6 +16,7 @@ + diff --git a/framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpHybridJsonSerializer.cs b/framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpHybridJsonSerializer.cs new file mode 100644 index 0000000000..6621ac8640 --- /dev/null +++ b/framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpHybridJsonSerializer.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Volo.Abp.DependencyInjection; + +namespace Volo.Abp.Json +{ + public class AbpHybridJsonSerializer : IJsonSerializer, ISingletonDependency + { + private readonly Lazy> _lazyProviders; + public List Providers => _lazyProviders.Value; + + public AbpHybridJsonSerializer(IOptions options, IServiceProvider serviceProvider) + { + _lazyProviders = new Lazy>( + () => options.Value + .Providers + .Select(c => serviceProvider.GetRequiredService(c) as IJsonSerializerProvider) + .Reverse() + .ToList(), + true + ); + } + + public string Serialize(object obj, bool camelCase = true, bool indented = false) + { + var provider = GetSerializerProvider(obj.GetType()); + return provider.Serialize(obj, camelCase, indented); + } + + public T Deserialize(string jsonString, bool camelCase = true) + { + var provider = GetSerializerProvider(typeof(T)); + return provider.Deserialize(jsonString, camelCase); + } + + public object Deserialize(Type type, string jsonString, bool camelCase = true) + { + var provider = GetSerializerProvider(type); + return provider.Deserialize(type, jsonString, camelCase); + } + + protected virtual IJsonSerializerProvider GetSerializerProvider(Type type) + { + foreach (var provider in Providers.Where(provider => provider.CanHandle(type))) + { + return provider; + } + + throw new AbpException($"There is no IJsonSerializerProvider that can handle {type.GetFullNameWithAssemblyName()} types!"); + } + } +} diff --git a/framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpJsonModule.cs b/framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpJsonModule.cs index c5376d0f05..747f01732a 100644 --- a/framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpJsonModule.cs +++ b/framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpJsonModule.cs @@ -1,6 +1,8 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Options; +using Volo.Abp.Json.Newtonsoft; +using Volo.Abp.Json.SystemTextJson; using Volo.Abp.Modularity; using Volo.Abp.Timing; @@ -11,7 +13,20 @@ namespace Volo.Abp.Json { public override void ConfigureServices(ServiceConfigurationContext context) { - context.Services.TryAddEnumerable(ServiceDescriptor.Transient, AbpJsonSerializerOptionsSetup>()); + context.Services.TryAddEnumerable(ServiceDescriptor + .Transient, + AbpSystemTextJsonSerializerOptionsSetup>()); + + Configure(options => + { + options.Providers.Add(); + options.Providers.Add(); + }); + + Configure(options => + { + options.IgnoreAttributes.Add(); + }); } } } diff --git a/framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpJsonOptions.cs b/framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpJsonOptions.cs index 239d7864cd..55a4683e26 100644 --- a/framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpJsonOptions.cs +++ b/framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpJsonOptions.cs @@ -1,4 +1,6 @@ -namespace Volo.Abp.Json +using Volo.Abp.Collections; + +namespace Volo.Abp.Json { public class AbpJsonOptions { @@ -6,5 +8,12 @@ /// Used to set default value for the DateTimeFormat. /// public string DefaultDateTimeFormat { get; set; } + + public ITypeList Providers { get; } + + public AbpJsonOptions() + { + Providers = new TypeList(); + } } } diff --git a/framework/src/Volo.Abp.Json/Volo/Abp/Json/IJsonSerializerProvider.cs b/framework/src/Volo.Abp.Json/Volo/Abp/Json/IJsonSerializerProvider.cs new file mode 100644 index 0000000000..f844dc5fd0 --- /dev/null +++ b/framework/src/Volo.Abp.Json/Volo/Abp/Json/IJsonSerializerProvider.cs @@ -0,0 +1,15 @@ +using System; + +namespace Volo.Abp.Json +{ + public interface IJsonSerializerProvider + { + bool CanHandle(Type type); + + string Serialize(object obj, bool camelCase = true, bool indented = false); + + T Deserialize(string jsonString, bool camelCase = true); + + object Deserialize(Type type, string jsonString, bool camelCase = true); + } +} diff --git a/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpJsonIsoDateTimeConverter.cs b/framework/src/Volo.Abp.Json/Volo/Abp/Json/Newtonsoft/AbpJsonIsoDateTimeConverter.cs similarity index 100% rename from framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpJsonIsoDateTimeConverter.cs rename to framework/src/Volo.Abp.Json/Volo/Abp/Json/Newtonsoft/AbpJsonIsoDateTimeConverter.cs diff --git a/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpNewtonsoftJsonSerializerOptions.cs b/framework/src/Volo.Abp.Json/Volo/Abp/Json/Newtonsoft/AbpNewtonsoftJsonSerializerOptions.cs similarity index 100% rename from framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpNewtonsoftJsonSerializerOptions.cs rename to framework/src/Volo.Abp.Json/Volo/Abp/Json/Newtonsoft/AbpNewtonsoftJsonSerializerOptions.cs diff --git a/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/NewtonsoftJsonSerializer.cs b/framework/src/Volo.Abp.Json/Volo/Abp/Json/Newtonsoft/NewtonsoftJsonSerializerProvider.cs similarity index 91% rename from framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/NewtonsoftJsonSerializer.cs rename to framework/src/Volo.Abp.Json/Volo/Abp/Json/Newtonsoft/NewtonsoftJsonSerializerProvider.cs index e241484719..e33f9b155f 100644 --- a/framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/NewtonsoftJsonSerializer.cs +++ b/framework/src/Volo.Abp.Json/Volo/Abp/Json/Newtonsoft/NewtonsoftJsonSerializerProvider.cs @@ -9,15 +9,14 @@ using Volo.Abp.DependencyInjection; namespace Volo.Abp.Json.Newtonsoft { - [Dependency(ReplaceServices = true)] - public class NewtonsoftJsonSerializer : IJsonSerializer, ITransientDependency + public class NewtonsoftJsonSerializerProvider : IJsonSerializerProvider, ITransientDependency { private static readonly CamelCaseExceptDictionaryKeysResolver SharedCamelCaseExceptDictionaryKeysResolver = new CamelCaseExceptDictionaryKeysResolver(); protected List Converters { get; } - public NewtonsoftJsonSerializer( + public NewtonsoftJsonSerializerProvider( IOptions options, IServiceProvider serviceProvider) { @@ -27,6 +26,11 @@ namespace Volo.Abp.Json.Newtonsoft .ToList(); } + public bool CanHandle(Type type) + { + return true; + } + public string Serialize(object obj, bool camelCase = true, bool indented = false) { return JsonConvert.SerializeObject(obj, CreateSerializerSettings(camelCase, indented)); diff --git a/framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpJsonSerializerOptions.cs b/framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/AbpSystemTextJsonSerializerOptions.cs similarity index 78% rename from framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpJsonSerializerOptions.cs rename to framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/AbpSystemTextJsonSerializerOptions.cs index c1289ce159..1f986e688b 100644 --- a/framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpJsonSerializerOptions.cs +++ b/framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/AbpSystemTextJsonSerializerOptions.cs @@ -1,12 +1,12 @@ using System.Text.Json; -namespace Volo.Abp.Json +namespace Volo.Abp.Json.SystemTextJson { - public class AbpJsonSerializerOptions + public class AbpSystemTextJsonSerializerOptions { public JsonSerializerOptions JsonSerializerOptions { get; } - public AbpJsonSerializerOptions() + public AbpSystemTextJsonSerializerOptions() { //TODO:Defaults? //https://github.com/dotnet/aspnetcore/blob/master/src/Mvc/Mvc.Core/src/JsonOptions.cs#L18 diff --git a/framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpJsonSerializerOptionsSetup.cs b/framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/AbpSystemTextJsonSerializerOptionsSetup.cs similarity index 59% rename from framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpJsonSerializerOptionsSetup.cs rename to framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/AbpSystemTextJsonSerializerOptionsSetup.cs index 16e8119731..4b56997d47 100644 --- a/framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpJsonSerializerOptionsSetup.cs +++ b/framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/AbpSystemTextJsonSerializerOptionsSetup.cs @@ -1,20 +1,21 @@ using System; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; -using Volo.Abp.Json.JsonConverters; +using Volo.Abp.Json.SystemTextJson; +using Volo.Abp.Json.SystemTextJson.JsonConverters; namespace Volo.Abp.Json { - public class AbpJsonSerializerOptionsSetup : IConfigureOptions + public class AbpSystemTextJsonSerializerOptionsSetup : IConfigureOptions { protected IServiceProvider ServiceProvider { get; } - public AbpJsonSerializerOptionsSetup(IServiceProvider serviceProvider) + public AbpSystemTextJsonSerializerOptionsSetup(IServiceProvider serviceProvider) { ServiceProvider = serviceProvider; } - public void Configure(AbpJsonSerializerOptions options) + public void Configure(AbpSystemTextJsonSerializerOptions options) { options.JsonSerializerOptions.Converters.Add(ServiceProvider.GetRequiredService()); options.JsonSerializerOptions.Converters.Add(ServiceProvider.GetRequiredService()); diff --git a/framework/src/Volo.Abp.Json/Volo/Abp/Json/JsonConverters/AbpDateTimeConverter.cs b/framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpDateTimeConverter.cs similarity index 81% rename from framework/src/Volo.Abp.Json/Volo/Abp/Json/JsonConverters/AbpDateTimeConverter.cs rename to framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpDateTimeConverter.cs index 29e99f285e..a87add029e 100644 --- a/framework/src/Volo.Abp.Json/Volo/Abp/Json/JsonConverters/AbpDateTimeConverter.cs +++ b/framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpDateTimeConverter.cs @@ -5,7 +5,7 @@ using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; using Volo.Abp.Timing; -namespace Volo.Abp.Json.JsonConverters +namespace Volo.Abp.Json.SystemTextJson.JsonConverters { public class AbpDateTimeConverter : JsonConverter, ITransientDependency { @@ -27,11 +27,11 @@ namespace Volo.Abp.Json.JsonConverters { if (_options.DefaultDateTimeFormat.IsNullOrWhiteSpace()) { - writer.WriteStringValue(value); + writer.WriteStringValue(_clock.Normalize(value)); } else { - writer.WriteStringValue(value.ToString(_options.DefaultDateTimeFormat)); + writer.WriteStringValue(_clock.Normalize(value).ToString(_options.DefaultDateTimeFormat)); } } } diff --git a/framework/src/Volo.Abp.Json/Volo/Abp/Json/JsonConverters/AbpNullableDateTimeConverter.cs b/framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpNullableDateTimeConverter.cs similarity index 84% rename from framework/src/Volo.Abp.Json/Volo/Abp/Json/JsonConverters/AbpNullableDateTimeConverter.cs rename to framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpNullableDateTimeConverter.cs index f061b94cf5..bad650b4d8 100644 --- a/framework/src/Volo.Abp.Json/Volo/Abp/Json/JsonConverters/AbpNullableDateTimeConverter.cs +++ b/framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpNullableDateTimeConverter.cs @@ -5,7 +5,7 @@ using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; using Volo.Abp.Timing; -namespace Volo.Abp.Json.JsonConverters +namespace Volo.Abp.Json.SystemTextJson.JsonConverters { public class AbpNullableDateTimeConverter : JsonConverter, ITransientDependency { @@ -38,11 +38,11 @@ namespace Volo.Abp.Json.JsonConverters { if (_options.DefaultDateTimeFormat.IsNullOrWhiteSpace()) { - writer.WriteStringValue(value.Value); + writer.WriteStringValue(_clock.Normalize(value.Value)); } else { - writer.WriteStringValue(value.Value.ToString(_options.DefaultDateTimeFormat)); + writer.WriteStringValue(_clock.Normalize(value.Value).ToString(_options.DefaultDateTimeFormat)); } } } diff --git a/framework/src/Volo.Abp.Json/Volo/Abp/Json/JsonConverters/ObjectToInferredTypesConverter.cs b/framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/JsonConverters/ObjectToInferredTypesConverter.cs similarity index 96% rename from framework/src/Volo.Abp.Json/Volo/Abp/Json/JsonConverters/ObjectToInferredTypesConverter.cs rename to framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/JsonConverters/ObjectToInferredTypesConverter.cs index c7497cfa60..02fa9bbaff 100644 --- a/framework/src/Volo.Abp.Json/Volo/Abp/Json/JsonConverters/ObjectToInferredTypesConverter.cs +++ b/framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/JsonConverters/ObjectToInferredTypesConverter.cs @@ -2,7 +2,7 @@ using System.Text.Json; using System.Text.Json.Serialization; -namespace Volo.Abp.Json.JsonConverters +namespace Volo.Abp.Json.SystemTextJson.JsonConverters { /// /// https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-converters-how-to#deserialize-inferred-types-to-object-properties diff --git a/framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpJsonSerializer.cs b/framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/SystemTextJsonSerializerProvider.cs similarity index 67% rename from framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpJsonSerializer.cs rename to framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/SystemTextJsonSerializerProvider.cs index 250111fee2..5a3429bff1 100644 --- a/framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpJsonSerializer.cs +++ b/framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/SystemTextJsonSerializerProvider.cs @@ -2,18 +2,27 @@ using System.Text.Json; using Microsoft.Extensions.Options; using Volo.Abp.DependencyInjection; +using Volo.Abp.Json.SystemTextJson; namespace Volo.Abp.Json { - public class AbpJsonSerializer : IJsonSerializer, ITransientDependency + public class SystemTextJsonSerializerProvider : IJsonSerializerProvider, ITransientDependency { - protected AbpJsonSerializerOptions Options { get; } + protected AbpSystemTextJsonSerializerOptions Options { get; } - public AbpJsonSerializer(IOptions options) + protected SystemTextJsonSupportTypes SystemTextJsonSupportTypes { get; } + + public SystemTextJsonSerializerProvider(IOptions options, SystemTextJsonSupportTypes systemTextJsonSupportTypes) { + SystemTextJsonSupportTypes = systemTextJsonSupportTypes; Options = options.Value; } + public bool CanHandle(Type type) + { + return SystemTextJsonSupportTypes.CanHandle(type); + } + public string Serialize(object obj, bool camelCase = true, bool indented = false) { return JsonSerializer.Serialize(obj, CreateJsonSerializerOptions(camelCase, indented)); diff --git a/framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/SystemTextJsonSupportTypes.cs b/framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/SystemTextJsonSupportTypes.cs new file mode 100644 index 0000000000..c2061e5b27 --- /dev/null +++ b/framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/SystemTextJsonSupportTypes.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.Extensions.Options; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Reflection; +using Volo.Abp.Timing; + +namespace Volo.Abp.Json.SystemTextJson +{ + public class SystemTextJsonSupportTypes : ITransientDependency + { + private static readonly List CacheTypes = new List(); + + private readonly SystemTextJsonSupportTypesOptions Options; + + public SystemTextJsonSupportTypes(IOptions options) + { + Options = options.Value; + } + + public bool CanHandle(Type type) + { + if (CacheTypes.Any(x => x == type)) + { + return false; + } + + if (type.GetCustomAttributes(true).Any(x => Options.IgnoreAttributes.Any(a => a == x.GetType()))) + { + CacheTypes.Add(type); + return false; + } + + if (type.DeclaringType != null && type.DeclaringType.GetCustomAttributes(true).Any(x => Options.IgnoreAttributes.Any(a => a == x.GetType()))) + { + CacheTypes.Add(type.DeclaringType); + return false; + } + + foreach (var propertyInfo in type.GetProperties()) + { + if (propertyInfo.IsDefined(typeof(DisableDateTimeNormalizationAttribute), true)) + { + CacheTypes.Add(propertyInfo.GetType()); + return false; + } + + if (!TypeHelper.IsPrimitiveExtended(type)) + { + if (!CanHandle(propertyInfo.PropertyType)) + { + CacheTypes.Add(propertyInfo.PropertyType); + return false; + } + } + } + + return true; + } + } +} diff --git a/framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/SystemTextJsonSupportTypesOptions.cs b/framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/SystemTextJsonSupportTypesOptions.cs new file mode 100644 index 0000000000..33ad53b997 --- /dev/null +++ b/framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/SystemTextJsonSupportTypesOptions.cs @@ -0,0 +1,15 @@ +using System; +using Volo.Abp.Collections; + +namespace Volo.Abp.Json.SystemTextJson +{ + public class SystemTextJsonSupportTypesOptions + { + public ITypeList IgnoreAttributes; + + public SystemTextJsonSupportTypesOptions() + { + IgnoreAttributes = new TypeList(); + } + } +} diff --git a/framework/test/Volo.Abp.Json.Tests/Volo.Abp.Json.Tests.csproj b/framework/test/Volo.Abp.Json.Tests/Volo.Abp.Json.Tests.csproj new file mode 100644 index 0000000000..fbc56e6ac2 --- /dev/null +++ b/framework/test/Volo.Abp.Json.Tests/Volo.Abp.Json.Tests.csproj @@ -0,0 +1,16 @@ + + + + + + net5.0 + + + + + + + + + + diff --git a/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpJsonTestBase.cs b/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpJsonTestBase.cs new file mode 100644 index 0000000000..5c9065ad80 --- /dev/null +++ b/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpJsonTestBase.cs @@ -0,0 +1,12 @@ +using Volo.Abp.Testing; + +namespace Volo.Abp.Json +{ + public abstract class AbpJsonTestBase : AbpIntegratedTest + { + protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options) + { + options.UseAutofac(); + } + } +} diff --git a/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpJsonTestModule.cs b/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpJsonTestModule.cs new file mode 100644 index 0000000000..ddbc08ac3f --- /dev/null +++ b/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpJsonTestModule.cs @@ -0,0 +1,15 @@ +using Volo.Abp.Autofac; +using Volo.Abp.Modularity; + +namespace Volo.Abp.Json +{ + [DependsOn( + typeof(AbpAutofacModule), + typeof(AbpJsonModule), + typeof(AbpTestBaseModule) + )] + public class AbpJsonTestModule : AbpModule + { + + } +} diff --git a/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/SystemTextJsonSupportTypes_Tests.cs b/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/SystemTextJsonSupportTypes_Tests.cs new file mode 100644 index 0000000000..b21cb94653 --- /dev/null +++ b/framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/SystemTextJsonSupportTypes_Tests.cs @@ -0,0 +1,65 @@ +using System; +using Shouldly; +using Volo.Abp.Json.SystemTextJson; +using Volo.Abp.Timing; +using Xunit; + +namespace Volo.Abp.Json +{ + public class SystemTextJsonSupportTypes_Tests : AbpJsonTestBase + { + private readonly SystemTextJsonSupportTypes _systemTextJsonSupportTypes; + + public SystemTextJsonSupportTypes_Tests() + { + _systemTextJsonSupportTypes = GetRequiredService(); + } + + [Fact] + public void Test() + { + _systemTextJsonSupportTypes.CanHandle(typeof(MyClass)).ShouldBeFalse(); + _systemTextJsonSupportTypes.CanHandle(typeof(MyClass2)).ShouldBeFalse(); + _systemTextJsonSupportTypes.CanHandle(typeof(MyClass3)).ShouldBeFalse(); + _systemTextJsonSupportTypes.CanHandle(typeof(MyClass4)).ShouldBeFalse(); + + _systemTextJsonSupportTypes.CanHandle(typeof(MyClass5)).ShouldBeTrue(); + _systemTextJsonSupportTypes.CanHandle(typeof(MyClass6)).ShouldBeTrue(); + } + + [DisableDateTimeNormalization] + class MyClass + { + public DateTime Prop1 { get; set; } + } + + class MyClass2 + { + [DisableDateTimeNormalization] + public DateTime Prop1 { get; set; } + } + + class MyClass3 + { + public MyClass4 Prop1 { get; set; } + } + + class MyClass4 + { + [DisableDateTimeNormalization] + public DateTime Prop1 { get; set; } + } + + class MyClass5 + { + public DateTime Prop1 { get; set; } + + public MyClass6 Prop2 { get; set; } + } + + class MyClass6 + { + public DateTime Prop1 { get; set; } + } + } +} diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/AbpFeatureManagementApplicationContractsModule.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/AbpFeatureManagementApplicationContractsModule.cs index c3ca6c2adc..32939a2430 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/AbpFeatureManagementApplicationContractsModule.cs +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/AbpFeatureManagementApplicationContractsModule.cs @@ -2,6 +2,7 @@ using Volo.Abp.Application; using Volo.Abp.FeatureManagement.JsonConverters; using Volo.Abp.Json; +using Volo.Abp.Json.SystemTextJson; using Volo.Abp.Modularity; using Volo.Abp.VirtualFileSystem; @@ -21,7 +22,7 @@ namespace Volo.Abp.FeatureManagement options.FileSets.AddEmbedded(); }); - Configure(options => + Configure(options => { options.JsonSerializerOptions.Converters.AddIfNotContains(new StringValueTypeJsonConverter()); }); diff --git a/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/ValueValidatorJsonConverter.cs b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/ValueValidatorJsonConverter.cs index bfea58b078..9d94cf8b55 100644 --- a/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/ValueValidatorJsonConverter.cs +++ b/modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/ValueValidatorJsonConverter.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Text.Json; using System.Text.Json.Serialization; -using Volo.Abp.Json.JsonConverters; +using Volo.Abp.Json.SystemTextJson.JsonConverters; using Volo.Abp.Validation.StringValues; namespace Volo.Abp.FeatureManagement.JsonConverters diff --git a/nupkg/common.ps1 b/nupkg/common.ps1 index 3df9140805..29cb13d9f3 100644 --- a/nupkg/common.ps1 +++ b/nupkg/common.ps1 @@ -109,7 +109,6 @@ $projects = ( "framework/src/Volo.Abp.Http", "framework/src/Volo.Abp.IdentityModel", "framework/src/Volo.Abp.Json", - "framework/src/Volo.Abp.Json.Newtonsoft", "framework/src/Volo.Abp.Ldap", "framework/src/Volo.Abp.Localization.Abstractions", "framework/src/Volo.Abp.MailKit",