mirror of https://github.com/abpframework/abp.git
57 changed files with 783 additions and 329 deletions
@ -0,0 +1,25 @@ |
|||||
|
using System; |
||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using Volo.Abp.Json.Microsoft; |
||||
|
using Volo.Abp.Json.Microsoft.JsonConverters; |
||||
|
|
||||
|
namespace Volo.Abp.AspNetCore.Mvc.Json |
||||
|
{ |
||||
|
public class AbpJsonOptionsSetup : IConfigureOptions<JsonOptions> |
||||
|
{ |
||||
|
protected IServiceProvider ServiceProvider { get; } |
||||
|
|
||||
|
public AbpJsonOptionsSetup(IServiceProvider serviceProvider) |
||||
|
{ |
||||
|
ServiceProvider = serviceProvider; |
||||
|
} |
||||
|
|
||||
|
public void Configure(JsonOptions options) |
||||
|
{ |
||||
|
options.JsonSerializerOptions.Converters.Add(ServiceProvider.GetRequiredService<AbpDateTimeConverter>()); |
||||
|
options.JsonSerializerOptions.Converters.Add(ServiceProvider.GetRequiredService<AbpNullableDateTimeConverter>()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,46 +0,0 @@ |
|||||
using Microsoft.Extensions.DependencyInjection; |
|
||||
using Newtonsoft.Json; |
|
||||
using Newtonsoft.Json.Serialization; |
|
||||
using System; |
|
||||
using System.Reflection; |
|
||||
using Volo.Abp.Json.Newtonsoft; |
|
||||
using Volo.Abp.Reflection; |
|
||||
using Volo.Abp.Timing; |
|
||||
|
|
||||
namespace Volo.Abp.AspNetCore.Mvc.Json |
|
||||
{ |
|
||||
public class AbpMvcJsonContractResolver : DefaultContractResolver |
|
||||
{ |
|
||||
private readonly Lazy<AbpJsonIsoDateTimeConverter> _dateTimeConverter; |
|
||||
|
|
||||
public AbpMvcJsonContractResolver(IServiceCollection services) |
|
||||
{ |
|
||||
_dateTimeConverter = services.GetServiceLazy<AbpJsonIsoDateTimeConverter>(); |
|
||||
|
|
||||
NamingStrategy = new CamelCaseNamingStrategy(); |
|
||||
} |
|
||||
|
|
||||
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) |
|
||||
{ |
|
||||
JsonProperty 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.Value; |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,39 +0,0 @@ |
|||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using System.Reflection; |
|
||||
using Newtonsoft.Json; |
|
||||
using Newtonsoft.Json.Serialization; |
|
||||
|
|
||||
namespace Volo.Abp.Auditing |
|
||||
{ |
|
||||
public class AuditingContractResolver : CamelCasePropertyNamesContractResolver |
|
||||
{ |
|
||||
private readonly List<Type> _ignoredTypes; |
|
||||
|
|
||||
public AuditingContractResolver(List<Type> ignoredTypes) |
|
||||
{ |
|
||||
_ignoredTypes = ignoredTypes; |
|
||||
} |
|
||||
|
|
||||
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) |
|
||||
{ |
|
||||
var property = base.CreateProperty(member, memberSerialization); |
|
||||
|
|
||||
if (member.IsDefined(typeof(DisableAuditingAttribute)) || member.IsDefined(typeof(JsonIgnoreAttribute))) |
|
||||
{ |
|
||||
property.ShouldSerialize = instance => false; |
|
||||
} |
|
||||
|
|
||||
foreach (var ignoredType in _ignoredTypes) |
|
||||
{ |
|
||||
if (ignoredType.GetTypeInfo().IsAssignableFrom(property.PropertyType)) |
|
||||
{ |
|
||||
property.ShouldSerialize = instance => false; |
|
||||
break; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return property; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,45 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text.Json; |
||||
|
using System.Text.Json.Serialization; |
||||
|
|
||||
|
namespace Volo.Abp.Auditing |
||||
|
{ |
||||
|
public class AuditingRuntimeIgnoreConverter : JsonConverter<Dictionary<string, object>> |
||||
|
{ |
||||
|
private readonly List<Type> _ignoredTypes; |
||||
|
|
||||
|
public AuditingRuntimeIgnoreConverter(List<Type> ignoredTypes) |
||||
|
{ |
||||
|
_ignoredTypes = ignoredTypes; |
||||
|
} |
||||
|
|
||||
|
public override Dictionary<string, object> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) |
||||
|
{ |
||||
|
throw new JsonException(); |
||||
|
} |
||||
|
|
||||
|
public override void Write(Utf8JsonWriter writer, Dictionary<string, object> value, JsonSerializerOptions options) |
||||
|
{ |
||||
|
var newDictionary = new Dictionary<string, object>(); |
||||
|
foreach (var item in value.Where(x => x.Value != null)) |
||||
|
{ |
||||
|
if (item.GetType().IsDefined(typeof(DisableAuditingAttribute), true) || |
||||
|
item.GetType().IsDefined(typeof(JsonIgnoreAttribute), true)) |
||||
|
{ |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
if (_ignoredTypes.Any(x => x.IsInstanceOfType(item.Value))) |
||||
|
{ |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
newDictionary[item.Key] = item.Value; |
||||
|
} |
||||
|
|
||||
|
JsonSerializer.Serialize(writer, newDictionary); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,29 @@ |
|||||
|
using System; |
||||
|
using System.Text.Json; |
||||
|
using System.Text.Json.Serialization; |
||||
|
|
||||
|
namespace Volo.Abp.Domain.Entities |
||||
|
{ |
||||
|
public class EntityJsonConverter<TEntity, TKey> : JsonConverter<TEntity> |
||||
|
{ |
||||
|
public override TEntity Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) |
||||
|
{ |
||||
|
var jsonDocument = JsonDocument.ParseValue(ref reader); |
||||
|
var entity = (TEntity)JsonSerializer.Deserialize(jsonDocument.RootElement.GetRawText(), typeToConvert); |
||||
|
var idJsonElement = jsonDocument.RootElement.GetProperty(nameof(IEntity<object>.Id)); |
||||
|
|
||||
|
var id = JsonSerializer.Deserialize<TKey>(idJsonElement.GetRawText()); |
||||
|
if (id != null) |
||||
|
{ |
||||
|
EntityHelper.TrySetId(entity, id); |
||||
|
} |
||||
|
|
||||
|
return entity; |
||||
|
} |
||||
|
|
||||
|
public override void Write(Utf8JsonWriter writer, TEntity value, JsonSerializerOptions options) |
||||
|
{ |
||||
|
JsonSerializer.Serialize(writer, value); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||
|
</Weavers> |
||||
@ -0,0 +1,30 @@ |
|||||
|
<?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> |
||||
@ -0,0 +1,25 @@ |
|||||
|
<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> |
||||
@ -0,0 +1,21 @@ |
|||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Microsoft.Extensions.DependencyInjection.Extensions; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using Volo.Abp.Json.Microsoft; |
||||
|
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>(); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,49 @@ |
|||||
|
using System; |
||||
|
using System.Text.Json; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace Volo.Abp.Json.Microsoft |
||||
|
{ |
||||
|
public class AbpJsonSerializer : IJsonSerializer, ITransientDependency |
||||
|
{ |
||||
|
protected AbpJsonSerializerOptions Options { get; } |
||||
|
|
||||
|
public AbpJsonSerializer(IOptions<AbpJsonSerializerOptions> options) |
||||
|
{ |
||||
|
Options = options.Value; |
||||
|
} |
||||
|
|
||||
|
public string Serialize(object obj, bool camelCase = true, bool indented = false) |
||||
|
{ |
||||
|
return JsonSerializer.Serialize(obj, CreateJsonSerializerOptions(camelCase, indented)); |
||||
|
} |
||||
|
|
||||
|
public T Deserialize<T>(string jsonString, bool camelCase = true) |
||||
|
{ |
||||
|
return JsonSerializer.Deserialize<T>(jsonString, CreateJsonSerializerOptions(camelCase)); |
||||
|
} |
||||
|
|
||||
|
public object Deserialize(Type type, string jsonString, bool camelCase = true) |
||||
|
{ |
||||
|
return JsonSerializer.Deserialize(jsonString, type, CreateJsonSerializerOptions(camelCase)); |
||||
|
} |
||||
|
|
||||
|
protected virtual JsonSerializerOptions CreateJsonSerializerOptions(bool camelCase = true, bool indented = false) |
||||
|
{ |
||||
|
var settings = new JsonSerializerOptions(Options.JsonSerializerOptions); |
||||
|
|
||||
|
if (camelCase) |
||||
|
{ |
||||
|
settings.PropertyNamingPolicy = JsonNamingPolicy.CamelCase; |
||||
|
} |
||||
|
|
||||
|
if (indented) |
||||
|
{ |
||||
|
settings.WriteIndented = true; |
||||
|
} |
||||
|
|
||||
|
return settings; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,18 @@ |
|||||
|
using System.Text.Json; |
||||
|
|
||||
|
namespace Volo.Abp.Json.Microsoft |
||||
|
{ |
||||
|
public class AbpJsonSerializerOptions |
||||
|
{ |
||||
|
public JsonSerializerOptions JsonSerializerOptions { get; } |
||||
|
|
||||
|
public AbpJsonSerializerOptions() |
||||
|
{ |
||||
|
//TODO:Defaults?
|
||||
|
//https://github.com/dotnet/aspnetcore/blob/master/src/Mvc/Mvc.Core/src/JsonOptions.cs#L18
|
||||
|
//https://github.com/dotnet/runtime/blob/master/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializerDefaults.cs
|
||||
|
|
||||
|
JsonSerializerOptions = new JsonSerializerOptions(JsonSerializerDefaults.Web); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,23 @@ |
|||||
|
using System; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using Volo.Abp.Json.Microsoft.JsonConverters; |
||||
|
|
||||
|
namespace Volo.Abp.Json.Microsoft |
||||
|
{ |
||||
|
public class AbpJsonSerializerOptionsSetup : IConfigureOptions<AbpJsonSerializerOptions> |
||||
|
{ |
||||
|
protected IServiceProvider ServiceProvider { get; } |
||||
|
|
||||
|
public AbpJsonSerializerOptionsSetup(IServiceProvider serviceProvider) |
||||
|
{ |
||||
|
ServiceProvider = serviceProvider; |
||||
|
} |
||||
|
|
||||
|
public void Configure(AbpJsonSerializerOptions options) |
||||
|
{ |
||||
|
options.JsonSerializerOptions.Converters.Add(ServiceProvider.GetRequiredService<AbpDateTimeConverter>()); |
||||
|
options.JsonSerializerOptions.Converters.Add(ServiceProvider.GetRequiredService<AbpNullableDateTimeConverter>()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,38 @@ |
|||||
|
using System; |
||||
|
using System.Text.Json; |
||||
|
using System.Text.Json.Serialization; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.Timing; |
||||
|
|
||||
|
namespace Volo.Abp.Json.Microsoft.JsonConverters |
||||
|
{ |
||||
|
public class AbpDateTimeConverter : JsonConverter<DateTime>, ITransientDependency |
||||
|
{ |
||||
|
private readonly IClock _clock; |
||||
|
private readonly AbpJsonOptions _options; |
||||
|
|
||||
|
public AbpDateTimeConverter(IClock clock, IOptions<AbpJsonOptions> abpJsonOptions) |
||||
|
{ |
||||
|
_clock = clock; |
||||
|
_options = abpJsonOptions.Value; |
||||
|
} |
||||
|
|
||||
|
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) |
||||
|
{ |
||||
|
return _clock.Normalize(reader.GetDateTime()); |
||||
|
} |
||||
|
|
||||
|
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) |
||||
|
{ |
||||
|
if (_options.DefaultDateTimeFormat.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
writer.WriteStringValue(_clock.Normalize(value)); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
writer.WriteStringValue(_clock.Normalize(value).ToString(_options.DefaultDateTimeFormat)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,50 @@ |
|||||
|
using System; |
||||
|
using System.Text.Json; |
||||
|
using System.Text.Json.Serialization; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.Timing; |
||||
|
|
||||
|
namespace Volo.Abp.Json.Microsoft.JsonConverters |
||||
|
{ |
||||
|
public class AbpNullableDateTimeConverter : JsonConverter<DateTime?>, ITransientDependency |
||||
|
{ |
||||
|
private readonly IClock _clock; |
||||
|
private readonly AbpJsonOptions _options; |
||||
|
|
||||
|
public AbpNullableDateTimeConverter(IClock clock, IOptions<AbpJsonOptions> abpJsonOptions) |
||||
|
{ |
||||
|
_clock = clock; |
||||
|
_options = abpJsonOptions.Value; |
||||
|
} |
||||
|
|
||||
|
public override DateTime? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) |
||||
|
{ |
||||
|
if (reader.TryGetDateTime(out var dateTime)) |
||||
|
{ |
||||
|
return _clock.Normalize(dateTime); |
||||
|
} |
||||
|
|
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
public override void Write(Utf8JsonWriter writer, DateTime? value, JsonSerializerOptions options) |
||||
|
{ |
||||
|
if (value == null) |
||||
|
{ |
||||
|
writer.WriteNullValue(); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
if (_options.DefaultDateTimeFormat.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
writer.WriteStringValue(_clock.Normalize(value.Value)); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
writer.WriteStringValue(_clock.Normalize(value.Value).ToString(_options.DefaultDateTimeFormat)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,54 @@ |
|||||
|
using System; |
||||
|
using System.Text.Json; |
||||
|
using System.Text.Json.Serialization; |
||||
|
|
||||
|
namespace Volo.Abp.Json.Microsoft.JsonConverters |
||||
|
{ |
||||
|
public class ObjectToInferredTypesConverter : JsonConverter<object> |
||||
|
{ |
||||
|
public override object Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) |
||||
|
{ |
||||
|
if (reader.TokenType == JsonTokenType.True) |
||||
|
{ |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
if (reader.TokenType == JsonTokenType.False) |
||||
|
{ |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
if (reader.TokenType == JsonTokenType.Number) |
||||
|
{ |
||||
|
if (reader.TryGetInt64(out var l)) |
||||
|
{ |
||||
|
return l; |
||||
|
} |
||||
|
|
||||
|
return reader.GetDouble(); |
||||
|
} |
||||
|
|
||||
|
if (reader.TokenType == JsonTokenType.String) |
||||
|
{ |
||||
|
if (reader.TryGetDateTime(out var datetime)) |
||||
|
{ |
||||
|
return datetime; |
||||
|
} |
||||
|
|
||||
|
return reader.GetString(); |
||||
|
} |
||||
|
|
||||
|
// Use JsonElement as fallback.
|
||||
|
// Newtonsoft uses JArray or JObject.
|
||||
|
using (var document = JsonDocument.ParseValue(ref reader)) |
||||
|
{ |
||||
|
return document.RootElement.Clone(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override void Write(Utf8JsonWriter writer, object objectToWrite, JsonSerializerOptions options) |
||||
|
{ |
||||
|
throw new InvalidOperationException("Should not get here."); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,52 +1,27 @@ |
|||||
using System; |
using System; |
||||
using System.Reflection; |
using System.Text.Json; |
||||
using System.Text; |
using Microsoft.Extensions.Options; |
||||
using Newtonsoft.Json; |
|
||||
using Newtonsoft.Json.Serialization; |
|
||||
using Volo.Abp.DependencyInjection; |
using Volo.Abp.DependencyInjection; |
||||
using Volo.Abp.Json; |
|
||||
|
|
||||
namespace Volo.Abp.Domain.Repositories.MemoryDb |
namespace Volo.Abp.Domain.Repositories.MemoryDb |
||||
{ |
{ |
||||
public class Utf8JsonMemoryDbSerializer : IMemoryDbSerializer, ITransientDependency |
public class Utf8JsonMemoryDbSerializer : IMemoryDbSerializer, ITransientDependency |
||||
{ |
{ |
||||
private static readonly JsonSerializerSettings MemoryDbSerializerSettings; |
protected Utf8JsonMemoryDbSerializerOptions Options { get; } |
||||
|
|
||||
static Utf8JsonMemoryDbSerializer() |
public Utf8JsonMemoryDbSerializer(IOptions<Utf8JsonMemoryDbSerializerOptions> options) |
||||
{ |
{ |
||||
MemoryDbSerializerSettings = new JsonSerializerSettings |
Options = options.Value; |
||||
{ |
|
||||
ContractResolver = new ResolverWithPrivateSetters(), |
|
||||
ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor |
|
||||
}; |
|
||||
} |
} |
||||
|
|
||||
byte[] IMemoryDbSerializer.Serialize(object obj) |
byte[] IMemoryDbSerializer.Serialize(object obj) |
||||
{ |
{ |
||||
var jsonString = JsonConvert.SerializeObject(obj, MemoryDbSerializerSettings); |
return JsonSerializer.SerializeToUtf8Bytes(obj, Options.JsonSerializerOptions); |
||||
return Encoding.UTF8.GetBytes(jsonString); |
|
||||
} |
} |
||||
|
|
||||
public object Deserialize(byte[] value, Type type) |
public object Deserialize(byte[] value, Type type) |
||||
{ |
{ |
||||
var jsonString = Encoding.UTF8.GetString(value); |
return JsonSerializer.Deserialize(value, type, Options.JsonSerializerOptions); |
||||
return JsonConvert.DeserializeObject(jsonString, type, MemoryDbSerializerSettings); |
|
||||
} |
|
||||
|
|
||||
public class ResolverWithPrivateSetters : DefaultContractResolver |
|
||||
{ |
|
||||
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) |
|
||||
{ |
|
||||
var prop = base.CreateProperty(member, memberSerialization); |
|
||||
if (prop.Writable) |
|
||||
{ |
|
||||
return prop; |
|
||||
} |
|
||||
|
|
||||
prop.Writable = member.As<PropertyInfo>()?.GetSetMethod(true) != null; |
|
||||
|
|
||||
return prop; |
|
||||
} |
|
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -0,0 +1,14 @@ |
|||||
|
using System.Text.Json; |
||||
|
|
||||
|
namespace Volo.Abp.Domain.Repositories.MemoryDb |
||||
|
{ |
||||
|
public class Utf8JsonMemoryDbSerializerOptions |
||||
|
{ |
||||
|
public JsonSerializerOptions JsonSerializerOptions { get; } |
||||
|
|
||||
|
public Utf8JsonMemoryDbSerializerOptions() |
||||
|
{ |
||||
|
JsonSerializerOptions = new JsonSerializerOptions(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,24 @@ |
|||||
|
using System; |
||||
|
using System.Text.Json; |
||||
|
using System.Text.Json.Serialization; |
||||
|
using Volo.Abp.Validation.StringValues; |
||||
|
|
||||
|
namespace Volo.Abp.FeatureManagement.JsonConverters |
||||
|
{ |
||||
|
public class LocalizableStringInfoJsonConverter : JsonConverter<LocalizableStringInfo> |
||||
|
{ |
||||
|
public override LocalizableStringInfo Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) |
||||
|
{ |
||||
|
var rootElement = JsonDocument.ParseValue(ref reader).RootElement; |
||||
|
return new LocalizableStringInfo( |
||||
|
rootElement.GetProperty("ResourceName").GetString(), |
||||
|
rootElement.GetProperty("Name").GetString() |
||||
|
); |
||||
|
} |
||||
|
|
||||
|
public override void Write(Utf8JsonWriter writer, LocalizableStringInfo value, JsonSerializerOptions options) |
||||
|
{ |
||||
|
JsonSerializer.Serialize(writer, value); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,36 @@ |
|||||
|
using System; |
||||
|
using System.Text.Json; |
||||
|
using System.Text.Json.Serialization; |
||||
|
using Volo.Abp.Validation.StringValues; |
||||
|
|
||||
|
namespace Volo.Abp.FeatureManagement.JsonConverters |
||||
|
{ |
||||
|
public class SelectionStringValueItemJsonConverter : JsonConverter<ISelectionStringValueItem> |
||||
|
{ |
||||
|
public override ISelectionStringValueItem Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) |
||||
|
{ |
||||
|
var rootElement = JsonDocument.ParseValue(ref reader).RootElement; |
||||
|
|
||||
|
var jsonSerializerOptions = new JsonSerializerOptions(); |
||||
|
jsonSerializerOptions.Converters.Add(new LocalizableStringInfoJsonConverter()); |
||||
|
|
||||
|
return new LocalizableSelectionStringValueItem |
||||
|
{ |
||||
|
Value = rootElement.GetProperty("Value").GetString(), |
||||
|
DisplayText = JsonSerializer.Deserialize<LocalizableStringInfo>(rootElement.GetProperty("DisplayText").GetRawText(), jsonSerializerOptions) |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
public override void Write(Utf8JsonWriter writer, ISelectionStringValueItem value, JsonSerializerOptions options) |
||||
|
{ |
||||
|
if (value.GetType() == typeof(LocalizableStringInfo)) |
||||
|
{ |
||||
|
JsonSerializer.Serialize(writer, (LocalizableSelectionStringValueItem)value); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
throw new JsonException("Unknown ISelectionStringValueItem type!"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,36 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Text.Json; |
||||
|
using System.Text.Json.Serialization; |
||||
|
using Volo.Abp.Validation.StringValues; |
||||
|
|
||||
|
namespace Volo.Abp.FeatureManagement.JsonConverters |
||||
|
{ |
||||
|
public class SelectionStringValueItemSourceJsonConverter : JsonConverter<ISelectionStringValueItemSource> |
||||
|
{ |
||||
|
public override ISelectionStringValueItemSource Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) |
||||
|
{ |
||||
|
var rootElement = JsonDocument.ParseValue(ref reader).RootElement; |
||||
|
var jsonSerializerOptions = new JsonSerializerOptions(); |
||||
|
jsonSerializerOptions.Converters.Add(new SelectionStringValueItemJsonConverter()); |
||||
|
|
||||
|
var selectionStringValueItem = |
||||
|
JsonSerializer.Deserialize<List<LocalizableSelectionStringValueItem>>(rootElement.GetProperty("Items").GetRawText(), jsonSerializerOptions) ?? |
||||
|
new List<LocalizableSelectionStringValueItem>(); |
||||
|
|
||||
|
return new StaticSelectionStringValueItemSource(selectionStringValueItem.ToArray()); |
||||
|
} |
||||
|
|
||||
|
public override void Write(Utf8JsonWriter writer, ISelectionStringValueItemSource value, JsonSerializerOptions options) |
||||
|
{ |
||||
|
if (value.GetType() == typeof(StaticSelectionStringValueItemSource)) |
||||
|
{ |
||||
|
JsonSerializer.Serialize(writer, (StaticSelectionStringValueItemSource)value); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
throw new JsonException("Unknown ISelectionStringValueItemSource type!"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,47 @@ |
|||||
|
using System; |
||||
|
using System.Text.Json; |
||||
|
using System.Text.Json.Serialization; |
||||
|
using Volo.Abp.Validation.StringValues; |
||||
|
|
||||
|
namespace Volo.Abp.FeatureManagement.JsonConverters |
||||
|
{ |
||||
|
public class StringValueTypeJsonConverter : JsonConverter<IStringValueType> |
||||
|
{ |
||||
|
public override IStringValueType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) |
||||
|
{ |
||||
|
var rootElement = JsonDocument.ParseValue(ref reader).RootElement; |
||||
|
var jsonSerializerOptions = new JsonSerializerOptions(); |
||||
|
jsonSerializerOptions.Converters.Add(new ValueValidatorJsonConverter()); |
||||
|
jsonSerializerOptions.Converters.Add(new SelectionStringValueItemSourceJsonConverter()); |
||||
|
|
||||
|
var name = rootElement.GetProperty("Name").GetString(); |
||||
|
return name switch |
||||
|
{ |
||||
|
"SelectionStringValueType" => JsonSerializer.Deserialize<SelectionStringValueType>(rootElement.GetRawText(), jsonSerializerOptions), |
||||
|
"FreeTextStringValueType" => JsonSerializer.Deserialize<FreeTextStringValueType>(rootElement.GetRawText(), jsonSerializerOptions), |
||||
|
"ToggleStringValueType" => JsonSerializer.Deserialize<ToggleStringValueType>(rootElement.GetRawText(), jsonSerializerOptions), |
||||
|
_ => throw new ArgumentException($"{nameof(IStringValueType)} named {name} was not found!") |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
public override void Write(Utf8JsonWriter writer, IStringValueType value, JsonSerializerOptions options) |
||||
|
{ |
||||
|
if (value.GetType() == typeof(FreeTextStringValueType)) |
||||
|
{ |
||||
|
JsonSerializer.Serialize(writer, (FreeTextStringValueType)value); |
||||
|
} |
||||
|
else if (value.GetType() == typeof(SelectionStringValueType)) |
||||
|
{ |
||||
|
JsonSerializer.Serialize(writer, (SelectionStringValueType)value); |
||||
|
} |
||||
|
else if (value.GetType() == typeof(ToggleStringValueType)) |
||||
|
{ |
||||
|
JsonSerializer.Serialize(writer, (ToggleStringValueType)value); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
throw new JsonException("Unknown IStringValueType type!"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,68 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using System.Text.Json; |
||||
|
using System.Text.Json.Serialization; |
||||
|
using Volo.Abp.Json.Microsoft.JsonConverters; |
||||
|
using Volo.Abp.Validation.StringValues; |
||||
|
|
||||
|
namespace Volo.Abp.FeatureManagement.JsonConverters |
||||
|
{ |
||||
|
public class ValueValidatorJsonConverter : JsonConverter<IValueValidator> |
||||
|
{ |
||||
|
public override IValueValidator Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) |
||||
|
{ |
||||
|
var rootElement = JsonDocument.ParseValue(ref reader).RootElement; |
||||
|
var valueValidator = CreateValueValidatorByName(rootElement.GetProperty("Name").GetString()); |
||||
|
|
||||
|
var deserializeOptions = new JsonSerializerOptions(); |
||||
|
deserializeOptions.Converters.Add(new ObjectToInferredTypesConverter()); |
||||
|
var properties = JsonSerializer.Deserialize<IDictionary<string, object>>(rootElement.GetProperty("Properties").GetRawText(), deserializeOptions); |
||||
|
if (properties != null && properties.Any()) |
||||
|
{ |
||||
|
foreach (var property in properties) |
||||
|
{ |
||||
|
valueValidator.Properties[property.Key] = property.Value; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return valueValidator; |
||||
|
} |
||||
|
|
||||
|
public override void Write(Utf8JsonWriter writer, IValueValidator value, JsonSerializerOptions options) |
||||
|
{ |
||||
|
if (value.GetType() == typeof(AlwaysValidValueValidator)) |
||||
|
{ |
||||
|
JsonSerializer.Serialize(writer, (AlwaysValidValueValidator)value); |
||||
|
} |
||||
|
else if (value.GetType() == typeof(BooleanValueValidator)) |
||||
|
{ |
||||
|
JsonSerializer.Serialize(writer, (BooleanValueValidator)value); |
||||
|
} |
||||
|
else if (value.GetType() == typeof(NumericValueValidator)) |
||||
|
{ |
||||
|
JsonSerializer.Serialize(writer, (NumericValueValidator)value); |
||||
|
} |
||||
|
else if (value.GetType() == typeof(StringValueValidator)) |
||||
|
{ |
||||
|
JsonSerializer.Serialize(writer, (StringValueValidator)value); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
throw new JsonException("Unknown IValueValidator type!"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
protected virtual IValueValidator CreateValueValidatorByName(string name) |
||||
|
{ |
||||
|
return name switch |
||||
|
{ |
||||
|
"NULL" => new AlwaysValidValueValidator(), |
||||
|
"BOOLEAN" => new BooleanValueValidator(), |
||||
|
"NUMERIC" => new NumericValueValidator(), |
||||
|
"STRING" => new StringValueValidator(), |
||||
|
_ => throw new ArgumentException($"{nameof(IValueValidator)} named {name} was not found!") |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,90 +0,0 @@ |
|||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using System.IO; |
|
||||
using System.Linq; |
|
||||
using Newtonsoft.Json; |
|
||||
using Newtonsoft.Json.Linq; |
|
||||
using Volo.Abp.DependencyInjection; |
|
||||
using Volo.Abp.Validation.StringValues; |
|
||||
|
|
||||
namespace Volo.Abp.FeatureManagement |
|
||||
{ |
|
||||
public class StringValueTypeJsonConverter : JsonConverter, ITransientDependency |
|
||||
{ |
|
||||
public override bool CanWrite => false; |
|
||||
|
|
||||
public override bool CanConvert(Type objectType) |
|
||||
{ |
|
||||
return objectType == typeof(IStringValueType); |
|
||||
} |
|
||||
|
|
||||
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) |
|
||||
{ |
|
||||
throw new NotImplementedException("This method should not be called to write (since CanWrite is false)."); |
|
||||
} |
|
||||
|
|
||||
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) |
|
||||
{ |
|
||||
if (reader.TokenType != JsonToken.StartObject) |
|
||||
{ |
|
||||
return null; |
|
||||
} |
|
||||
|
|
||||
var jsonObject = JObject.Load(reader); |
|
||||
|
|
||||
var stringValue = CreateStringValueTypeByName(jsonObject, jsonObject["name"].ToString()); |
|
||||
foreach (var o in serializer.Deserialize<Dictionary<string, object>>( |
|
||||
new JsonTextReader(new StringReader(jsonObject["properties"].ToString())))) |
|
||||
{ |
|
||||
stringValue[o.Key] = o.Value; |
|
||||
} |
|
||||
|
|
||||
stringValue.Validator = CreateValueValidatorByName(jsonObject["validator"], jsonObject["validator"]["name"].ToString()); |
|
||||
foreach (var o in serializer.Deserialize<Dictionary<string, object>>( |
|
||||
new JsonTextReader(new StringReader(jsonObject["validator"]["properties"].ToString())))) |
|
||||
{ |
|
||||
stringValue.Validator[o.Key] = o.Value; |
|
||||
} |
|
||||
|
|
||||
return stringValue; |
|
||||
} |
|
||||
|
|
||||
protected virtual IStringValueType CreateStringValueTypeByName(JObject jObject, string name) |
|
||||
{ |
|
||||
if (name == "SelectionStringValueType") |
|
||||
{ |
|
||||
var selectionStringValueType = new SelectionStringValueType(); |
|
||||
if (jObject["itemSource"].HasValues) |
|
||||
{ |
|
||||
selectionStringValueType.ItemSource = new StaticSelectionStringValueItemSource(jObject["itemSource"]["items"] |
|
||||
.Select(item => new LocalizableSelectionStringValueItem() |
|
||||
{ |
|
||||
Value = item["value"].ToString(), |
|
||||
DisplayText = new LocalizableStringInfo(item["displayText"]["resourceName"].ToString(), item["displayText"]["name"].ToString()) |
|
||||
}).ToArray()); |
|
||||
} |
|
||||
|
|
||||
return selectionStringValueType; |
|
||||
} |
|
||||
|
|
||||
return name switch |
|
||||
{ |
|
||||
"FreeTextStringValueType" => new FreeTextStringValueType(), |
|
||||
"ToggleStringValueType" => new ToggleStringValueType(), |
|
||||
_ => throw new ArgumentException($"{nameof(IStringValueType)} named {name} was not found!") |
|
||||
}; |
|
||||
} |
|
||||
|
|
||||
protected virtual IValueValidator CreateValueValidatorByName(JToken jObject, string name) |
|
||||
{ |
|
||||
return name switch |
|
||||
{ |
|
||||
"NULL" => new AlwaysValidValueValidator(), |
|
||||
"BOOLEAN" => new BooleanValueValidator(), |
|
||||
"NUMERIC" => new NumericValueValidator(), |
|
||||
"STRING" => new StringValueValidator(), |
|
||||
_ => throw new ArgumentException($"{nameof(IValueValidator)} named {name} was not found!") |
|
||||
}; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
Loading…
Reference in new issue