Browse Source

Add AbpHybridJsonSerializer, AbpHybridJsonInputFormatter, AbpHybridJsonOutputFormatter.

pull/5952/head
maliming 5 years ago
parent
commit
8c28ee1dd2
  1. 12
      framework/Volo.Abp.sln
  2. 1
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj
  3. 2
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/AbpAspNetCoreMvcModule.cs
  4. 38
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpHybridJsonInputFormatter.cs
  5. 35
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpHybridJsonOutputFormatter.cs
  6. 3
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpJsonOptionsSetup.cs
  7. 45
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpMvcJsonContractResolver.cs
  8. 22
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpMvcNewtonsoftJsonOptionsSetup.cs
  9. 22
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/MediaTypeHeaderValues.cs
  10. 82
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/MvcCoreBuilderExtensions.cs
  11. 2
      framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ValueConverters/AbpJsonValueConverter.cs
  12. 2
      framework/src/Volo.Abp.EntityFrameworkCore/Volo/Abp/EntityFrameworkCore/ValueConverters/ExtraPropertiesValueConverter.cs
  13. 3
      framework/src/Volo.Abp.Json.Newtonsoft/FodyWeavers.xml
  14. 30
      framework/src/Volo.Abp.Json.Newtonsoft/FodyWeavers.xsd
  15. 25
      framework/src/Volo.Abp.Json.Newtonsoft/Volo.Abp.Json.Newtonsoft.csproj
  16. 21
      framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/AbpJsonModule.cs
  17. 1
      framework/src/Volo.Abp.Json/Volo.Abp.Json.csproj
  18. 55
      framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpHybridJsonSerializer.cs
  19. 17
      framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpJsonModule.cs
  20. 11
      framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpJsonOptions.cs
  21. 15
      framework/src/Volo.Abp.Json/Volo/Abp/Json/IJsonSerializerProvider.cs
  22. 0
      framework/src/Volo.Abp.Json/Volo/Abp/Json/Newtonsoft/AbpJsonIsoDateTimeConverter.cs
  23. 0
      framework/src/Volo.Abp.Json/Volo/Abp/Json/Newtonsoft/AbpNewtonsoftJsonSerializerOptions.cs
  24. 10
      framework/src/Volo.Abp.Json/Volo/Abp/Json/Newtonsoft/NewtonsoftJsonSerializerProvider.cs
  25. 6
      framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/AbpSystemTextJsonSerializerOptions.cs
  26. 9
      framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/AbpSystemTextJsonSerializerOptionsSetup.cs
  27. 6
      framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpDateTimeConverter.cs
  28. 6
      framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpNullableDateTimeConverter.cs
  29. 2
      framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/JsonConverters/ObjectToInferredTypesConverter.cs
  30. 15
      framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/SystemTextJsonSerializerProvider.cs
  31. 62
      framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/SystemTextJsonSupportTypes.cs
  32. 15
      framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/SystemTextJsonSupportTypesOptions.cs
  33. 16
      framework/test/Volo.Abp.Json.Tests/Volo.Abp.Json.Tests.csproj
  34. 12
      framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpJsonTestBase.cs
  35. 15
      framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpJsonTestModule.cs
  36. 65
      framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/SystemTextJsonSupportTypes_Tests.cs
  37. 3
      modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/AbpFeatureManagementApplicationContractsModule.cs
  38. 2
      modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/ValueValidatorJsonConverter.cs
  39. 1
      nupkg/common.ps1

12
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}

1
framework/src/Volo.Abp.AspNetCore.Mvc/Volo.Abp.AspNetCore.Mvc.csproj

@ -28,6 +28,7 @@
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="5.0.0-rc.2.*" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="5.0.0-rc.2.*" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning" Version="4.1.1" />
</ItemGroup>

2
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<IConfigureOptions<JsonOptions>, AbpJsonOptionsSetup>());
mvcCoreBuilder.AddAbpHybridJson();
Configure<MvcRazorRuntimeCompilationOptions>(options =>
{

38
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<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)
{
return await GetTextInputFormatter(context).ReadRequestBodyAsync(context, encoding);
}
private TextInputFormatter GetTextInputFormatter(InputFormatterContext context)
{
if (context.HttpContext.RequestServices.GetRequiredService<SystemTextJsonSupportTypes>().CanHandle(context.ModelType))
{
return context.HttpContext.RequestServices.GetRequiredService<SystemTextJsonInputFormatter>();
}
return context.HttpContext.RequestServices.GetRequiredService<NewtonsoftJsonInputFormatter>();
}
public InputFormatterExceptionPolicy ExceptionPolicy => InputFormatterExceptionPolicy.MalformedInputExceptions;
}
}

35
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<SystemTextJsonSupportTypes>().CanHandle(context.ObjectType))
{
return context.HttpContext.RequestServices.GetRequiredService<SystemTextJsonOutputFormatter>();
}
return context.HttpContext.RequestServices.GetRequiredService<NewtonsoftJsonOutputFormatter>();
}
}
}

3
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
{

45
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<DisableDateTimeNormalizationAttribute>(member) == null)
{
property.Converter = _dateTimeConverter;
}
}
}
}

22
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<MvcNewtonsoftJsonOptions>
{
protected IServiceProvider ServiceProvider { get; }
public AbpMvcNewtonsoftJsonOptionsSetup(IServiceProvider serviceProvider)
{
ServiceProvider = serviceProvider;
}
public void Configure(MvcNewtonsoftJsonOptions options)
{
options.SerializerSettings.ContractResolver = ServiceProvider.GetRequiredService<AbpMvcJsonContractResolver>();
}
}
}

22
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
{
/// <summary>
/// https://github.com/dotnet/aspnetcore/blob/master/src/Mvc/Mvc.NewtonsoftJson/src/MediaTypeHeaderValues.cs
/// </summary>
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();
}
}

82
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<IOptions<JsonOptions>>();
var logger = provider.GetRequiredService<ILoggerFactory>().CreateLogger<SystemTextJsonInputFormatter>();
return new SystemTextJsonInputFormatter(jsonOptions.Value, logger);
});
//NewtonsoftJsonInputFormatter
builder.Services.AddTransient(provider =>
{
var jsonOptions = provider.GetRequiredService<IOptions<MvcNewtonsoftJsonOptions>>().Value;
return new NewtonsoftJsonInputFormatter(
provider.GetRequiredService<ILoggerFactory>().CreateLogger<NewtonsoftJsonInputFormatter>(),
jsonOptions.SerializerSettings,
provider.GetRequiredService<ArrayPool<char>>(),
provider.GetRequiredService<DefaultObjectPoolProvider>(),
provider.GetRequiredService<IOptions<MvcOptions>>().Value,
jsonOptions);
});
//SystemTextJsonOutputFormatter
builder.Services.AddTransient(provider =>
{
var jsonSerializerOptions = provider.GetRequiredService<IOptions<JsonOptions>>().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<IOptions<MvcNewtonsoftJsonOptions>>().Value;
return new NewtonsoftJsonOutputFormatter(
jsonOptions.SerializerSettings,
provider.GetRequiredService<ArrayPool<char>>(),
provider.GetRequiredService<IOptions<MvcOptions>>().Value);
});
builder.Services.TryAddEnumerable(ServiceDescriptor.Transient<IConfigureOptions<JsonOptions>, AbpJsonOptionsSetup>());
builder.Services.TryAddEnumerable(ServiceDescriptor.Transient<IConfigureOptions<MvcNewtonsoftJsonOptions>, AbpMvcNewtonsoftJsonOptionsSetup>());
builder.Services.Configure<MvcOptions>(options =>
{
options.InputFormatters.RemoveType<SystemTextJsonInputFormatter>();
options.InputFormatters.RemoveType<NewtonsoftJsonInputFormatter>();
options.InputFormatters.Add(new AbpHybridJsonInputFormatter());
options.OutputFormatters.RemoveType<SystemTextJsonOutputFormatter>();
options.OutputFormatters.RemoveType<NewtonsoftJsonOutputFormatter>();
options.OutputFormatters.Add(new AbpHybridJsonOutputFormatter());
});
return builder;
}
}
}

2
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
{

2
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

3
framework/src/Volo.Abp.Json.Newtonsoft/FodyWeavers.xml

@ -1,3 +0,0 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
framework/src/Volo.Abp.Json.Newtonsoft/FodyWeavers.xsd

@ -1,30 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

25
framework/src/Volo.Abp.Json.Newtonsoft/Volo.Abp.Json.Newtonsoft.csproj

@ -1,25 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\configureawait.props" />
<Import Project="..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Volo.Abp.Json.Newtonsoft</AssemblyName>
<PackageId>Volo.Abp.Json.Newtonsoft</PackageId>
<AssetTargetFallback>$(AssetTargetFallback);portable-net45+win8+wp8+wpa81;</AssetTargetFallback>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Json\Volo.Abp.Json.csproj" />
</ItemGroup>
</Project>

21
framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/AbpJsonModule.cs

@ -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<AbpNewtonsoftJsonSerializerOptions>(options =>
{
options.Converters.Add<AbpJsonIsoDateTimeConverter>();
});
}
}
}

1
framework/src/Volo.Abp.Json/Volo.Abp.Json.csproj

@ -16,6 +16,7 @@
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Timing\Volo.Abp.Timing.csproj" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
</ItemGroup>
</Project>

55
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<List<IJsonSerializerProvider>> _lazyProviders;
public List<IJsonSerializerProvider> Providers => _lazyProviders.Value;
public AbpHybridJsonSerializer(IOptions<AbpJsonOptions> options, IServiceProvider serviceProvider)
{
_lazyProviders = new Lazy<List<IJsonSerializerProvider>>(
() => 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<T>(string jsonString, bool camelCase = true)
{
var provider = GetSerializerProvider(typeof(T));
return provider.Deserialize<T>(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!");
}
}
}

17
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<IConfigureOptions<AbpJsonSerializerOptions>, AbpJsonSerializerOptionsSetup>());
context.Services.TryAddEnumerable(ServiceDescriptor
.Transient<IConfigureOptions<AbpSystemTextJsonSerializerOptions>,
AbpSystemTextJsonSerializerOptionsSetup>());
Configure<AbpJsonOptions>(options =>
{
options.Providers.Add<NewtonsoftJsonSerializerProvider>();
options.Providers.Add<SystemTextJsonSerializerProvider>();
});
Configure<SystemTextJsonSupportTypesOptions>(options =>
{
options.IgnoreAttributes.Add<DisableDateTimeNormalizationAttribute>();
});
}
}
}

11
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.
/// </summary>
public string DefaultDateTimeFormat { get; set; }
public ITypeList<IJsonSerializerProvider> Providers { get; }
public AbpJsonOptions()
{
Providers = new TypeList<IJsonSerializerProvider>();
}
}
}

15
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<T>(string jsonString, bool camelCase = true);
object Deserialize(Type type, string jsonString, bool camelCase = true);
}
}

0
framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpJsonIsoDateTimeConverter.cs → framework/src/Volo.Abp.Json/Volo/Abp/Json/Newtonsoft/AbpJsonIsoDateTimeConverter.cs

0
framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/AbpNewtonsoftJsonSerializerOptions.cs → framework/src/Volo.Abp.Json/Volo/Abp/Json/Newtonsoft/AbpNewtonsoftJsonSerializerOptions.cs

10
framework/src/Volo.Abp.Json.Newtonsoft/Volo/Abp/Json/Newtonsoft/NewtonsoftJsonSerializer.cs → 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<JsonConverter> Converters { get; }
public NewtonsoftJsonSerializer(
public NewtonsoftJsonSerializerProvider(
IOptions<AbpNewtonsoftJsonSerializerOptions> 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));

6
framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpJsonSerializerOptions.cs → 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

9
framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpJsonSerializerOptionsSetup.cs → 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<AbpJsonSerializerOptions>
public class AbpSystemTextJsonSerializerOptionsSetup : IConfigureOptions<AbpSystemTextJsonSerializerOptions>
{
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<AbpDateTimeConverter>());
options.JsonSerializerOptions.Converters.Add(ServiceProvider.GetRequiredService<AbpNullableDateTimeConverter>());

6
framework/src/Volo.Abp.Json/Volo/Abp/Json/JsonConverters/AbpDateTimeConverter.cs → 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<DateTime>, 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));
}
}
}

6
framework/src/Volo.Abp.Json/Volo/Abp/Json/JsonConverters/AbpNullableDateTimeConverter.cs → 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<DateTime?>, 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));
}
}
}

2
framework/src/Volo.Abp.Json/Volo/Abp/Json/JsonConverters/ObjectToInferredTypesConverter.cs → 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
{
/// <summary>
/// https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-converters-how-to#deserialize-inferred-types-to-object-properties

15
framework/src/Volo.Abp.Json/Volo/Abp/Json/AbpJsonSerializer.cs → 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<AbpJsonSerializerOptions> options)
protected SystemTextJsonSupportTypes SystemTextJsonSupportTypes { get; }
public SystemTextJsonSerializerProvider(IOptions<AbpSystemTextJsonSerializerOptions> 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));

62
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<Type> CacheTypes = new List<Type>();
private readonly SystemTextJsonSupportTypesOptions Options;
public SystemTextJsonSupportTypes(IOptions<SystemTextJsonSupportTypesOptions> 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;
}
}
}

15
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<Attribute> IgnoreAttributes;
public SystemTextJsonSupportTypesOptions()
{
IgnoreAttributes = new TypeList<Attribute>();
}
}
}

16
framework/test/Volo.Abp.Json.Tests/Volo.Abp.Json.Tests.csproj

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\common.test.props" />
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.6.1" />
<ProjectReference Include="..\..\src\Volo.Abp.Json\Volo.Abp.Json.csproj" />
<ProjectReference Include="..\..\src\Volo.Abp.Autofac\Volo.Abp.Autofac.csproj" />
<ProjectReference Include="..\AbpTestBase\AbpTestBase.csproj" />
</ItemGroup>
</Project>

12
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<AbpJsonTestModule>
{
protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options)
{
options.UseAutofac();
}
}
}

15
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
{
}
}

65
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<SystemTextJsonSupportTypes>();
}
[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; }
}
}
}

3
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<AbpFeatureManagementApplicationContractsModule>();
});
Configure<AbpJsonSerializerOptions>(options =>
Configure<AbpSystemTextJsonSerializerOptions>(options =>
{
options.JsonSerializerOptions.Converters.AddIfNotContains(new StringValueTypeJsonConverter());
});

2
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

1
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",

Loading…
Cancel
Save