mirror of https://github.com/abpframework/abp.git
committed by
GitHub
67 changed files with 1320 additions and 248 deletions
@ -0,0 +1,39 @@ |
|||
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); |
|||
} |
|||
|
|||
protected virtual TextInputFormatter GetTextInputFormatter(InputFormatterContext context) |
|||
{ |
|||
var typesMatcher = context.HttpContext.RequestServices.GetRequiredService<AbpSystemTextJsonUnsupportedTypeMatcher>(); |
|||
if (!typesMatcher.Match(context.ModelType)) |
|||
{ |
|||
return context.HttpContext.RequestServices.GetRequiredService<SystemTextJsonInputFormatter>(); |
|||
} |
|||
|
|||
return context.HttpContext.RequestServices.GetRequiredService<NewtonsoftJsonInputFormatter>(); |
|||
} |
|||
|
|||
public virtual InputFormatterExceptionPolicy ExceptionPolicy => InputFormatterExceptionPolicy.MalformedInputExceptions; |
|||
} |
|||
} |
|||
@ -0,0 +1,37 @@ |
|||
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); |
|||
} |
|||
|
|||
protected virtual TextOutputFormatter GetTextInputFormatter(OutputFormatterWriteContext context) |
|||
{ |
|||
var typesMatcher = context.HttpContext.RequestServices.GetRequiredService<AbpSystemTextJsonUnsupportedTypeMatcher>(); |
|||
if (!typesMatcher.Match(context.ObjectType)) |
|||
{ |
|||
return context.HttpContext.RequestServices.GetRequiredService<SystemTextJsonOutputFormatter>(); |
|||
} |
|||
|
|||
return context.HttpContext.RequestServices.GetRequiredService<NewtonsoftJsonOutputFormatter>(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,28 @@ |
|||
using System; |
|||
using System.Text.Json; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Options; |
|||
using Volo.Abp.Json.SystemTextJson.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.ReadCommentHandling = JsonCommentHandling.Skip; |
|||
options.JsonSerializerOptions.AllowTrailingCommas = true; |
|||
|
|||
options.JsonSerializerOptions.Converters.Add(ServiceProvider.GetRequiredService<AbpDateTimeConverter>()); |
|||
options.JsonSerializerOptions.Converters.Add(ServiceProvider.GetRequiredService<AbpNullableDateTimeConverter>()); |
|||
} |
|||
} |
|||
} |
|||
@ -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>(); |
|||
} |
|||
} |
|||
} |
|||
@ -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(); |
|||
} |
|||
} |
|||
@ -0,0 +1,83 @@ |
|||
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); |
|||
}); |
|||
|
|||
builder.Services.AddTransient<DefaultObjectPoolProvider>(); |
|||
//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; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,62 @@ |
|||
using System; |
|||
using System.Linq; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Options; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace Volo.Abp.Json |
|||
{ |
|||
public class AbpHybridJsonSerializer : IJsonSerializer, ITransientDependency |
|||
{ |
|||
protected AbpJsonOptions Options { get; } |
|||
|
|||
protected IServiceScopeFactory ServiceScopeFactory { get; } |
|||
|
|||
public AbpHybridJsonSerializer(IOptions<AbpJsonOptions> options, IServiceScopeFactory serviceScopeFactory) |
|||
{ |
|||
Options = options.Value; |
|||
ServiceScopeFactory = serviceScopeFactory; |
|||
} |
|||
|
|||
public string Serialize(object obj, bool camelCase = true, bool indented = false) |
|||
{ |
|||
using (var scope = ServiceScopeFactory.CreateScope()) |
|||
{ |
|||
var serializerProvider = GetSerializerProvider(scope.ServiceProvider, obj.GetType()); |
|||
return serializerProvider.Serialize(obj, camelCase, indented); |
|||
} |
|||
} |
|||
|
|||
public T Deserialize<T>(string jsonString, bool camelCase = true) |
|||
{ |
|||
using (var scope = ServiceScopeFactory.CreateScope()) |
|||
{ |
|||
var serializerProvider = GetSerializerProvider(scope.ServiceProvider, typeof(T)); |
|||
return serializerProvider.Deserialize<T>(jsonString, camelCase); |
|||
} |
|||
} |
|||
|
|||
public object Deserialize(Type type, string jsonString, bool camelCase = true) |
|||
{ |
|||
using (var scope = ServiceScopeFactory.CreateScope()) |
|||
{ |
|||
var serializerProvider = GetSerializerProvider(scope.ServiceProvider, type); |
|||
return serializerProvider.Deserialize(type, jsonString, camelCase); |
|||
} |
|||
} |
|||
|
|||
protected virtual IJsonSerializerProvider GetSerializerProvider(IServiceProvider serviceProvider, Type type) |
|||
{ |
|||
foreach (var providerType in Options.Providers.Reverse()) |
|||
{ |
|||
var provider = serviceProvider.GetRequiredService(providerType) as IJsonSerializerProvider; |
|||
if (provider.CanHandle(type)) |
|||
{ |
|||
return provider; |
|||
} |
|||
} |
|||
|
|||
throw new AbpException($"There is no IJsonSerializerProvider that can handle '{type.GetFullNameWithAssemblyName()}'!"); |
|||
} |
|||
} |
|||
} |
|||
@ -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,0 +1,23 @@ |
|||
using System.Text.Json; |
|||
using Volo.Abp.Collections; |
|||
|
|||
namespace Volo.Abp.Json.SystemTextJson |
|||
{ |
|||
public class AbpSystemTextJsonSerializerOptions |
|||
{ |
|||
public JsonSerializerOptions JsonSerializerOptions { get; } |
|||
|
|||
public ITypeList UnsupportedTypes { get; } |
|||
|
|||
public AbpSystemTextJsonSerializerOptions() |
|||
{ |
|||
JsonSerializerOptions = new JsonSerializerOptions(JsonSerializerDefaults.Web) |
|||
{ |
|||
ReadCommentHandling = JsonCommentHandling.Skip, |
|||
AllowTrailingCommas = true |
|||
}; |
|||
|
|||
UnsupportedTypes = new TypeList(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,24 @@ |
|||
using System; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Microsoft.Extensions.Options; |
|||
using Volo.Abp.Json.SystemTextJson; |
|||
using Volo.Abp.Json.SystemTextJson.JsonConverters; |
|||
|
|||
namespace Volo.Abp.Json |
|||
{ |
|||
public class AbpSystemTextJsonSerializerOptionsSetup : IConfigureOptions<AbpSystemTextJsonSerializerOptions> |
|||
{ |
|||
protected IServiceProvider ServiceProvider { get; } |
|||
|
|||
public AbpSystemTextJsonSerializerOptionsSetup(IServiceProvider serviceProvider) |
|||
{ |
|||
ServiceProvider = serviceProvider; |
|||
} |
|||
|
|||
public void Configure(AbpSystemTextJsonSerializerOptions options) |
|||
{ |
|||
options.JsonSerializerOptions.Converters.Add(ServiceProvider.GetRequiredService<AbpDateTimeConverter>()); |
|||
options.JsonSerializerOptions.Converters.Add(ServiceProvider.GetRequiredService<AbpNullableDateTimeConverter>()); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,59 @@ |
|||
using System; |
|||
using System.Text.Json; |
|||
using Microsoft.Extensions.Options; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace Volo.Abp.Json.SystemTextJson |
|||
{ |
|||
public class AbpSystemTextJsonSerializerProvider : IJsonSerializerProvider, ITransientDependency |
|||
{ |
|||
protected AbpSystemTextJsonSerializerOptions Options { get; } |
|||
|
|||
protected AbpSystemTextJsonUnsupportedTypeMatcher AbpSystemTextJsonUnsupportedTypeMatcher { get; } |
|||
|
|||
public AbpSystemTextJsonSerializerProvider( |
|||
IOptions<AbpSystemTextJsonSerializerOptions> options, |
|||
AbpSystemTextJsonUnsupportedTypeMatcher abpSystemTextJsonUnsupportedTypeMatcher) |
|||
{ |
|||
AbpSystemTextJsonUnsupportedTypeMatcher = abpSystemTextJsonUnsupportedTypeMatcher; |
|||
Options = options.Value; |
|||
} |
|||
|
|||
public bool CanHandle(Type type) |
|||
{ |
|||
return !AbpSystemTextJsonUnsupportedTypeMatcher.Match(type); |
|||
} |
|||
|
|||
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,21 @@ |
|||
using System; |
|||
using Microsoft.Extensions.Options; |
|||
using Volo.Abp.DependencyInjection; |
|||
|
|||
namespace Volo.Abp.Json.SystemTextJson |
|||
{ |
|||
public class AbpSystemTextJsonUnsupportedTypeMatcher : ITransientDependency |
|||
{ |
|||
protected AbpSystemTextJsonSerializerOptions Options { get; } |
|||
|
|||
public AbpSystemTextJsonUnsupportedTypeMatcher(IOptions<AbpSystemTextJsonSerializerOptions> options) |
|||
{ |
|||
Options = options.Value; |
|||
} |
|||
|
|||
public virtual bool Match(Type type) |
|||
{ |
|||
return Options.UnsupportedTypes.Contains(type); |
|||
} |
|||
} |
|||
} |
|||
@ -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.SystemTextJson.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.SystemTextJson.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,57 @@ |
|||
using System; |
|||
using System.Text.Json; |
|||
using System.Text.Json.Serialization; |
|||
|
|||
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
|
|||
/// </summary>
|
|||
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.Reflection; |
|||
using System.Text; |
|||
using Newtonsoft.Json; |
|||
using Newtonsoft.Json.Serialization; |
|||
using System.Text.Json; |
|||
using Microsoft.Extensions.Options; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Json; |
|||
|
|||
namespace Volo.Abp.Domain.Repositories.MemoryDb |
|||
{ |
|||
public class Utf8JsonMemoryDbSerializer : IMemoryDbSerializer, ITransientDependency |
|||
{ |
|||
private static readonly JsonSerializerSettings MemoryDbSerializerSettings; |
|||
protected Utf8JsonMemoryDbSerializerOptions Options { get; } |
|||
|
|||
static Utf8JsonMemoryDbSerializer() |
|||
public Utf8JsonMemoryDbSerializer(IOptions<Utf8JsonMemoryDbSerializerOptions> options) |
|||
{ |
|||
MemoryDbSerializerSettings = new JsonSerializerSettings |
|||
{ |
|||
ContractResolver = new ResolverWithPrivateSetters(), |
|||
ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor |
|||
}; |
|||
Options = options.Value; |
|||
} |
|||
|
|||
byte[] IMemoryDbSerializer.Serialize(object obj) |
|||
{ |
|||
var jsonString = JsonConvert.SerializeObject(obj, MemoryDbSerializerSettings); |
|||
return Encoding.UTF8.GetBytes(jsonString); |
|||
return JsonSerializer.SerializeToUtf8Bytes(obj, Options.JsonSerializerOptions); |
|||
} |
|||
|
|||
public object Deserialize(byte[] value, Type type) |
|||
{ |
|||
var jsonString = Encoding.UTF8.GetString(value); |
|||
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; |
|||
} |
|||
return JsonSerializer.Deserialize(value, type, Options.JsonSerializerOptions); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
@ -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,67 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Shouldly; |
|||
using Xunit; |
|||
|
|||
namespace Volo.Abp.Auditing |
|||
{ |
|||
public class JsonNetAuditSerializer_Test : AbpAuditingTestBase |
|||
{ |
|||
private readonly JsonNetAuditSerializer _jsonNetAuditSerializer; |
|||
|
|||
public JsonNetAuditSerializer_Test() |
|||
{ |
|||
_jsonNetAuditSerializer = GetRequiredService<JsonNetAuditSerializer>(); |
|||
} |
|||
|
|||
protected override void AfterAddApplication(IServiceCollection services) |
|||
{ |
|||
services.Configure<AbpAuditingOptions>(options => |
|||
{ |
|||
options.IgnoredTypes.Add(typeof(DateTime)); |
|||
}); |
|||
|
|||
base.AfterAddApplication(services); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Serialize_Test() |
|||
{ |
|||
var arguments = new Dictionary<string, object> |
|||
{ |
|||
{"input", new InputDto {PersonData = "IdCard:123123"}}, |
|||
{"input2", new Input2Dto {UserName = "admin", Password = "1q2w3E*", Birthday = DateTime.Now}} |
|||
}; |
|||
|
|||
var str = _jsonNetAuditSerializer.Serialize(arguments); |
|||
|
|||
str.ShouldNotContain("IdCard"); |
|||
str.ShouldNotContain("1q2w3E*"); |
|||
str.ShouldNotContain("Birthday"); |
|||
|
|||
str.ShouldContain("UserName"); |
|||
str.ShouldContain("admin"); |
|||
} |
|||
|
|||
|
|||
[DisableAuditing] |
|||
class InputDto |
|||
{ |
|||
public string PersonData { get; set; } |
|||
} |
|||
|
|||
class Input2Dto |
|||
{ |
|||
public string UserName { get; set; } |
|||
|
|||
[DisableAuditing] |
|||
public string Password { get; set; } |
|||
|
|||
[Newtonsoft.Json.JsonIgnore] |
|||
public string PrivateEmail { get; set; } |
|||
|
|||
public DateTime Birthday { get; set; } |
|||
} |
|||
} |
|||
} |
|||
@ -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> |
|||
@ -0,0 +1,125 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Reflection; |
|||
using System.Text.Json; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Newtonsoft.Json; |
|||
using Newtonsoft.Json.Serialization; |
|||
using Shouldly; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Json.Newtonsoft; |
|||
using Volo.Abp.Json.SystemTextJson; |
|||
using Xunit; |
|||
using JsonSerializer = Newtonsoft.Json.JsonSerializer; |
|||
|
|||
namespace Volo.Abp.Json |
|||
{ |
|||
public class AbpHybridJsonSerializer_Tests : AbpJsonTestBase |
|||
{ |
|||
private readonly IJsonSerializer _jsonSerializer; |
|||
|
|||
public AbpHybridJsonSerializer_Tests() |
|||
{ |
|||
_jsonSerializer = GetRequiredService<IJsonSerializer>(); |
|||
} |
|||
|
|||
protected override void AfterAddApplication(IServiceCollection services) |
|||
{ |
|||
services.Configure<AbpSystemTextJsonSerializerOptions>(options => |
|||
{ |
|||
options.UnsupportedTypes.Add<MyClass1>(); |
|||
|
|||
options.JsonSerializerOptions.Converters.Add(new SystemTextJsonConverter()); |
|||
}); |
|||
|
|||
services.Configure<AbpNewtonsoftJsonSerializerOptions>(options => |
|||
{ |
|||
options.Converters.Add<NewtonsoftJsonConverter>(); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void NewtonsoftSerialize_Test() |
|||
{ |
|||
var json = _jsonSerializer.Serialize(new MyClass1 |
|||
{ |
|||
Providers = new List<MyClass3> |
|||
{ |
|||
new MyClass3() |
|||
} |
|||
}); |
|||
|
|||
json.ShouldContain("Newtonsoft"); |
|||
} |
|||
|
|||
[Fact] |
|||
public void SystemTextJsonSerialize_Test() |
|||
{ |
|||
var json = _jsonSerializer.Serialize(new MyClass2 |
|||
{ |
|||
Providers = new List<MyClass3> |
|||
{ |
|||
new MyClass3() |
|||
} |
|||
}); |
|||
|
|||
json.ShouldContain("SystemTextJson"); |
|||
} |
|||
|
|||
public class MyClass1 |
|||
{ |
|||
public string Provider { get; set; } |
|||
|
|||
public List<MyClass3> Providers { get; set; } |
|||
} |
|||
|
|||
public class MyClass2 |
|||
{ |
|||
public string Provider { get; set; } |
|||
|
|||
public List<MyClass3> Providers { get; set; } |
|||
} |
|||
|
|||
public class MyClass3 |
|||
{ |
|||
public string Provider { get; set; } |
|||
} |
|||
|
|||
class NewtonsoftJsonConverter : JsonConverter<MyClass1>, ITransientDependency |
|||
{ |
|||
public override void WriteJson(JsonWriter writer, MyClass1 value, JsonSerializer serializer) |
|||
{ |
|||
value.Provider = "Newtonsoft"; |
|||
foreach (var provider in value.Providers) |
|||
{ |
|||
provider.Provider = "Newtonsoft"; |
|||
} |
|||
|
|||
writer.WriteRawValue(JsonConvert.SerializeObject(value)); |
|||
} |
|||
|
|||
public override MyClass1 ReadJson(JsonReader reader, Type objectType, MyClass1 existingValue, bool hasExistingValue, JsonSerializer serializer) |
|||
{ |
|||
return (MyClass1)serializer.Deserialize(reader, objectType); |
|||
} |
|||
} |
|||
|
|||
class SystemTextJsonConverter : System.Text.Json.Serialization.JsonConverter<MyClass2>, ITransientDependency |
|||
{ |
|||
public override void Write(Utf8JsonWriter writer, MyClass2 value, JsonSerializerOptions options) |
|||
{ |
|||
value.Provider = "SystemTextJson"; |
|||
foreach (var provider in value.Providers) |
|||
{ |
|||
provider.Provider = "SystemTextJson"; |
|||
} |
|||
System.Text.Json.JsonSerializer.Serialize(writer, value); |
|||
} |
|||
|
|||
public override MyClass2 Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) |
|||
{ |
|||
return (MyClass2)System.Text.Json.JsonSerializer.Deserialize(ref reader, typeToConvert); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -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(); |
|||
} |
|||
} |
|||
} |
|||
@ -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 |
|||
{ |
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,66 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Shouldly; |
|||
using Volo.Abp.Json.SystemTextJson; |
|||
using Xunit; |
|||
|
|||
namespace Volo.Abp.Json |
|||
{ |
|||
public class AbpSystemTextJsonUnsupportedTypeMatcher_Tests : AbpJsonTestBase |
|||
{ |
|||
private readonly AbpSystemTextJsonUnsupportedTypeMatcher _abpSystemTextJsonUnsupportedTypeMatcher; |
|||
|
|||
public AbpSystemTextJsonUnsupportedTypeMatcher_Tests() |
|||
{ |
|||
_abpSystemTextJsonUnsupportedTypeMatcher = GetRequiredService<AbpSystemTextJsonUnsupportedTypeMatcher>(); |
|||
} |
|||
|
|||
protected override void AfterAddApplication(IServiceCollection services) |
|||
{ |
|||
services.Configure<AbpSystemTextJsonSerializerOptions>(options => |
|||
{ |
|||
options.UnsupportedTypes.Add<MyClass>(); |
|||
options.UnsupportedTypes.Add<byte[]>(); |
|||
options.UnsupportedTypes.Add<Dictionary<string, MyClass4>>(); |
|||
}); |
|||
} |
|||
|
|||
[Fact] |
|||
public void Match_Test() |
|||
{ |
|||
_abpSystemTextJsonUnsupportedTypeMatcher.Match(typeof(MyClass)).ShouldBeTrue(); |
|||
_abpSystemTextJsonUnsupportedTypeMatcher.Match(typeof(byte[])).ShouldBeTrue(); |
|||
|
|||
_abpSystemTextJsonUnsupportedTypeMatcher.Match(typeof(MyClass2)).ShouldBeFalse(); |
|||
_abpSystemTextJsonUnsupportedTypeMatcher.Match(typeof(MyClass3)).ShouldBeFalse(); |
|||
_abpSystemTextJsonUnsupportedTypeMatcher.Match(typeof(MyClass4)).ShouldBeFalse(); |
|||
|
|||
_abpSystemTextJsonUnsupportedTypeMatcher.Match(typeof(string)).ShouldBeFalse(); |
|||
_abpSystemTextJsonUnsupportedTypeMatcher.Match(typeof(string[])).ShouldBeFalse(); |
|||
|
|||
_abpSystemTextJsonUnsupportedTypeMatcher.Match(typeof(Dictionary<string, MyClass4>)).ShouldBeTrue(); |
|||
_abpSystemTextJsonUnsupportedTypeMatcher.Match(typeof(IDictionary<string, MyClass4>)).ShouldBeFalse(); |
|||
} |
|||
|
|||
class MyClass |
|||
{ |
|||
public DateTime Prop1 { get; set; } |
|||
} |
|||
|
|||
class MyClass2 |
|||
{ |
|||
public DateTime Prop1 { get; set; } |
|||
} |
|||
|
|||
class MyClass3 |
|||
{ |
|||
public MyClass4 Prop1 { get; set; } |
|||
} |
|||
|
|||
class MyClass4 |
|||
{ |
|||
public DateTime Prop1 { get; set; } |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
using System; |
|||
using System.Text.Json; |
|||
using System.Text.Json.Serialization; |
|||
using Volo.Abp.Domain.Entities; |
|||
|
|||
namespace Volo.Abp.MemoryDb.JsonConverters |
|||
{ |
|||
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) |
|||
{ |
|||
var newOptions = new JsonSerializerOptions(options); |
|||
newOptions.Converters.Remove(this); |
|||
var entityConverter = (JsonConverter<TEntity>)newOptions.GetConverter(typeof(TEntity)); |
|||
entityConverter.Write(writer, value, newOptions); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,17 @@ |
|||
using System.Collections.Generic; |
|||
using System.Text.Json; |
|||
using System.Text.Json.Serialization; |
|||
|
|||
namespace Volo.Abp.FeatureManagement.JsonConverters |
|||
{ |
|||
internal static class JsonSerializerOptionsHelper |
|||
{ |
|||
public static JsonSerializerOptions Create(JsonSerializerOptions baseOptions, JsonConverter removeConverter, params JsonConverter[] addConverters) |
|||
{ |
|||
var options = new JsonSerializerOptions(baseOptions); |
|||
options.Converters.RemoveAll(x => x == removeConverter); |
|||
options.Converters.AddIfNotContains(addConverters); |
|||
return options; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,32 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
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 newOptions = JsonSerializerOptionsHelper.Create(options, this); |
|||
|
|||
var rootElement = JsonDocument.ParseValue(ref reader).RootElement; |
|||
var items = rootElement.EnumerateObject().FirstOrDefault(x => x.Name.Equals("Items", StringComparison.InvariantCultureIgnoreCase)).Value.GetRawText(); |
|||
|
|||
var selectionStringValueItem = |
|||
JsonSerializer.Deserialize<List<LocalizableSelectionStringValueItem>>(items, newOptions) ?? |
|||
new List<LocalizableSelectionStringValueItem>(); |
|||
|
|||
return new StaticSelectionStringValueItemSource(selectionStringValueItem.ToArray()); |
|||
} |
|||
|
|||
public override void Write(Utf8JsonWriter writer, ISelectionStringValueItemSource value, JsonSerializerOptions options) |
|||
{ |
|||
var newOptions = JsonSerializerOptionsHelper.Create(options, this); |
|||
JsonSerializer.Serialize(writer, value, value.GetType(), newOptions); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,31 @@ |
|||
using System; |
|||
using System.Linq; |
|||
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 name = rootElement.EnumerateObject().FirstOrDefault(x => x.Name.Equals("Name", StringComparison.InvariantCultureIgnoreCase)).Value.GetString(); |
|||
var newOptions = JsonSerializerOptionsHelper.Create(options, this, new ValueValidatorJsonConverter(), new SelectionStringValueItemSourceJsonConverter()); |
|||
return name switch |
|||
{ |
|||
"SelectionStringValueType" => JsonSerializer.Deserialize<SelectionStringValueType>(rootElement.GetRawText(), newOptions), |
|||
"FreeTextStringValueType" => JsonSerializer.Deserialize<FreeTextStringValueType>(rootElement.GetRawText(), newOptions), |
|||
"ToggleStringValueType" => JsonSerializer.Deserialize<ToggleStringValueType>(rootElement.GetRawText(), newOptions), |
|||
_ => throw new ArgumentException($"{nameof(IStringValueType)} named {name} was not found!") |
|||
}; |
|||
} |
|||
|
|||
public override void Write(Utf8JsonWriter writer, IStringValueType value, JsonSerializerOptions options) |
|||
{ |
|||
var newOptions = JsonSerializerOptionsHelper.Create(options, this); |
|||
JsonSerializer.Serialize(writer, value, value.GetType(), newOptions); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,51 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text.Json; |
|||
using System.Text.Json.Serialization; |
|||
using Volo.Abp.Json.SystemTextJson.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 name = rootElement.EnumerateObject().FirstOrDefault(x => x.Name.Equals("Name", StringComparison.InvariantCultureIgnoreCase)).Value.GetString(); |
|||
var valueValidator = CreateValueValidatorByName(name); |
|||
|
|||
var propertiesRawText = rootElement.EnumerateObject().FirstOrDefault(x => x.Name.Equals("Properties", StringComparison.InvariantCultureIgnoreCase)).Value.GetRawText(); |
|||
var newOptions = JsonSerializerOptionsHelper.Create(options, this, new ObjectToInferredTypesConverter()); |
|||
var properties = JsonSerializer.Deserialize<IDictionary<string, object>>(propertiesRawText, newOptions); |
|||
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) |
|||
{ |
|||
var newOptions = JsonSerializerOptionsHelper.Create(options, this); |
|||
JsonSerializer.Serialize(writer, value, value.GetType(), newOptions); |
|||
} |
|||
|
|||
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