Browse Source

Merge pull request #6196 from abpframework/maliming/json-patch

Handling the case where JSON is null or empty.
pull/6207/head
liangshiwei 6 years ago
committed by GitHub
parent
commit
e830401d72
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 26
      framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpDateTimeConverter.cs
  2. 20
      framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpHasExtraPropertiesJsonConverter.cs
  3. 23
      framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpNullableDateTimeConverter.cs
  4. 239
      framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpSystemTextJsonSerializerProvider_Tests.cs
  5. 23
      framework/test/Volo.Abp.MemoryDb.Tests/Volo/Abp/MemoryDb/JsonConverters/EntityJsonConverter.cs
  6. 21
      modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/SelectionStringValueItemSourceJsonConverter.cs
  7. 26
      modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/StringValueTypeJsonConverter.cs
  8. 27
      modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/ValueValidatorJsonConverter.cs
  9. 11
      modules/feature-management/test/Volo.Abp.FeatureManagement.Application.Tests/Volo/Abp/FeatureManagement/StringValueJsonConverter_Tests.cs

26
framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpDateTimeConverter.cs

@ -1,4 +1,5 @@
using System; using System;
using System.Globalization;
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
@ -20,7 +21,28 @@ namespace Volo.Abp.Json.SystemTextJson.JsonConverters
public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{ {
return _clock.Normalize(reader.GetDateTime()); if (!_options.DefaultDateTimeFormat.IsNullOrWhiteSpace())
{
if (reader.TokenType == JsonTokenType.String)
{
var s = reader.GetString();
if (DateTime.TryParseExact(s, _options.DefaultDateTimeFormat, CultureInfo.CurrentUICulture, DateTimeStyles.None, out var d1))
{
return _clock.Normalize(d1);
}
throw new JsonException($"'{s}' can't parse to DateTime({_options.DefaultDateTimeFormat})!");
}
throw new JsonException("Reader's TokenType is not String!");
}
if (reader.TryGetDateTime(out var d2))
{
return _clock.Normalize(d2);
}
throw new JsonException("Can't get datetime from the reader!");
} }
public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options)
@ -31,7 +53,7 @@ namespace Volo.Abp.Json.SystemTextJson.JsonConverters
} }
else else
{ {
writer.WriteStringValue(_clock.Normalize(value).ToString(_options.DefaultDateTimeFormat)); writer.WriteStringValue(_clock.Normalize(value).ToString(_options.DefaultDateTimeFormat, CultureInfo.CurrentUICulture));
} }
} }
} }

20
framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpHasExtraPropertiesJsonConverter.cs

@ -16,15 +16,21 @@ namespace Volo.Abp.Json.SystemTextJson.JsonConverters
x.GetType() == typeof(AbpHasExtraPropertiesJsonConverterFactory)); x.GetType() == typeof(AbpHasExtraPropertiesJsonConverterFactory));
var rootElement = JsonDocument.ParseValue(ref reader).RootElement; var rootElement = JsonDocument.ParseValue(ref reader).RootElement;
var extensibleObject = JsonSerializer.Deserialize<T>(rootElement.GetRawText(), newOptions); if (rootElement.ValueKind == JsonValueKind.Object)
{
var extensibleObject = JsonSerializer.Deserialize<T>(rootElement.GetRawText(), newOptions);
var extraProperties = rootElement.EnumerateObject().FirstOrDefault(x => var extraPropertiesJsonProperty = rootElement.EnumerateObject().FirstOrDefault(x => x.Name.Equals(nameof(IHasExtraProperties.ExtraProperties), StringComparison.OrdinalIgnoreCase));
x.Name.Equals(nameof(IHasExtraProperties.ExtraProperties), StringComparison.OrdinalIgnoreCase)) if (extraPropertiesJsonProperty.Value.ValueKind == JsonValueKind.Object)
.Value.GetRawText(); {
var extraPropertyDictionary = JsonSerializer.Deserialize(extraProperties, typeof(ExtraPropertyDictionary), newOptions); var extraPropertyDictionary = JsonSerializer.Deserialize(extraPropertiesJsonProperty.Value.GetRawText(), typeof(ExtraPropertyDictionary), newOptions);
ObjectHelper.TrySetProperty(extensibleObject, x => x.ExtraProperties, () => extraPropertyDictionary); ObjectHelper.TrySetProperty(extensibleObject, x => x.ExtraProperties, () => extraPropertyDictionary);
}
return extensibleObject; return extensibleObject;
}
throw new JsonException("RootElement's ValueKind is not Object!");
} }
public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)

23
framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpNullableDateTimeConverter.cs

@ -1,4 +1,5 @@
using System; using System;
using System.Globalization;
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
@ -20,9 +21,25 @@ namespace Volo.Abp.Json.SystemTextJson.JsonConverters
public override DateTime? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) public override DateTime? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{ {
if (reader.TryGetDateTime(out var dateTime)) if (!_options.DefaultDateTimeFormat.IsNullOrWhiteSpace())
{ {
return _clock.Normalize(dateTime); if (reader.TokenType == JsonTokenType.String)
{
var s = reader.GetString();
if (DateTime.TryParseExact(s, _options.DefaultDateTimeFormat, CultureInfo.CurrentUICulture, DateTimeStyles.None, out var d1))
{
return _clock.Normalize(d1);
}
throw new JsonException($"'{s}' can't parse to DateTime({_options.DefaultDateTimeFormat})!");
}
throw new JsonException("Reader's TokenType is not String!");
}
if (reader.TryGetDateTime(out var d2))
{
return _clock.Normalize(d2);
} }
return null; return null;
@ -42,7 +59,7 @@ namespace Volo.Abp.Json.SystemTextJson.JsonConverters
} }
else else
{ {
writer.WriteStringValue(_clock.Normalize(value.Value).ToString(_options.DefaultDateTimeFormat)); writer.WriteStringValue(_clock.Normalize(value.Value).ToString(_options.DefaultDateTimeFormat, CultureInfo.CurrentUICulture));
} }
} }
} }

239
framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpSystemTextJsonSerializerProvider_Tests.cs

@ -1,30 +1,89 @@
using Shouldly; using System;
using Microsoft.Extensions.DependencyInjection;
using Shouldly;
using Volo.Abp.Data; using Volo.Abp.Data;
using Volo.Abp.Json.SystemTextJson; using Volo.Abp.Json.SystemTextJson;
using Volo.Abp.ObjectExtending; using Volo.Abp.ObjectExtending;
using Volo.Abp.Timing;
using Xunit; using Xunit;
namespace Volo.Abp.Json namespace Volo.Abp.Json
{ {
public class AbpSystemTextJsonSerializerProvider_Tests : AbpJsonTestBase public abstract class AbpSystemTextJsonSerializerProvider_TestBase : AbpJsonTestBase
{ {
private readonly AbpSystemTextJsonSerializerProvider _jsonSerializer; protected AbpSystemTextJsonSerializerProvider JsonSerializer;
public AbpSystemTextJsonSerializerProvider_Tests() public AbpSystemTextJsonSerializerProvider_TestBase()
{ {
_jsonSerializer = GetRequiredService<AbpSystemTextJsonSerializerProvider>(); JsonSerializer = GetRequiredService<AbpSystemTextJsonSerializerProvider>();
} }
public class TestExtensibleObjectClass : ExtensibleObject
{
public string Name { get; set; }
}
public class FileWithBoolean
{
public string Name { get; set; }
public bool IsDeleted { get; set; }
}
public class FileWithNullableBoolean
{
public string Name { get; set; }
public bool? IsDeleted { get; set; }
}
public class FileWithEnum
{
public string Name { get; set; }
public FileType Type { get; set; }
}
public class FileWithNullableEnum
{
public string Name { get; set; }
public FileType? Type { get; set; }
}
public enum FileType
{
Zip = 0,
Exe = 2
}
public class FileWithDatetime
{
public string Name { get; set; }
public DateTime CreationTime { get; set; }
}
public class FileWithNullableDatetime
{
public string Name { get; set; }
public DateTime? CreationTime { get; set; }
}
}
public class AbpSystemTextJsonSerializerProvider_Tests : AbpSystemTextJsonSerializerProvider_TestBase
{
[Fact] [Fact]
public void Serialize_Deserialize_With_Boolean() public void Serialize_Deserialize_With_Boolean()
{ {
var json = "{\"name\":\"abp\",\"IsDeleted\":\"fAlSe\"}"; var json = "{\"name\":\"abp\",\"IsDeleted\":\"fAlSe\"}";
var file = _jsonSerializer.Deserialize<FileWithBoolean>(json); var file = JsonSerializer.Deserialize<FileWithBoolean>(json);
file.Name.ShouldBe("abp"); file.Name.ShouldBe("abp");
file.IsDeleted.ShouldBeFalse(); file.IsDeleted.ShouldBeFalse();
file.IsDeleted = false; file.IsDeleted = false;
var newJson = _jsonSerializer.Serialize(file); var newJson = JsonSerializer.Serialize(file);
newJson.ShouldBe("{\"name\":\"abp\",\"isDeleted\":false}"); newJson.ShouldBe("{\"name\":\"abp\",\"isDeleted\":false}");
} }
@ -32,19 +91,19 @@ namespace Volo.Abp.Json
public void Serialize_Deserialize_With_Nullable_Boolean() public void Serialize_Deserialize_With_Nullable_Boolean()
{ {
var json = "{\"name\":\"abp\",\"IsDeleted\":null}"; var json = "{\"name\":\"abp\",\"IsDeleted\":null}";
var file = _jsonSerializer.Deserialize<FileWithNullableBoolean>(json); var file = JsonSerializer.Deserialize<FileWithNullableBoolean>(json);
file.Name.ShouldBe("abp"); file.Name.ShouldBe("abp");
file.IsDeleted.ShouldBeNull(); file.IsDeleted.ShouldBeNull();
var newJson = _jsonSerializer.Serialize(file); var newJson = JsonSerializer.Serialize(file);
newJson.ShouldBe("{\"name\":\"abp\",\"isDeleted\":null}"); newJson.ShouldBe("{\"name\":\"abp\",\"isDeleted\":null}");
json = "{\"name\":\"abp\",\"IsDeleted\":\"true\"}"; json = "{\"name\":\"abp\",\"IsDeleted\":\"true\"}";
file = _jsonSerializer.Deserialize<FileWithNullableBoolean>(json); file = JsonSerializer.Deserialize<FileWithNullableBoolean>(json);
file.IsDeleted.ShouldNotBeNull(); file.IsDeleted.ShouldNotBeNull();
file.IsDeleted.Value.ShouldBeTrue(); file.IsDeleted.Value.ShouldBeTrue();
newJson = _jsonSerializer.Serialize(file); newJson = JsonSerializer.Serialize(file);
newJson.ShouldBe("{\"name\":\"abp\",\"isDeleted\":true}"); newJson.ShouldBe("{\"name\":\"abp\",\"isDeleted\":true}");
} }
@ -52,11 +111,11 @@ namespace Volo.Abp.Json
public void Serialize_Deserialize_With_Enum() public void Serialize_Deserialize_With_Enum()
{ {
var json = "{\"name\":\"abp\",\"type\":\"Exe\"}"; var json = "{\"name\":\"abp\",\"type\":\"Exe\"}";
var file = _jsonSerializer.Deserialize<FileWithEnum>(json); var file = JsonSerializer.Deserialize<FileWithEnum>(json);
file.Name.ShouldBe("abp"); file.Name.ShouldBe("abp");
file.Type.ShouldBe(FileType.Exe); file.Type.ShouldBe(FileType.Exe);
var newJson = _jsonSerializer.Serialize(file); var newJson = JsonSerializer.Serialize(file);
newJson.ShouldBe("{\"name\":\"abp\",\"type\":2}"); newJson.ShouldBe("{\"name\":\"abp\",\"type\":2}");
} }
@ -64,72 +123,178 @@ namespace Volo.Abp.Json
public void Serialize_Deserialize_With_Nullable_Enum() public void Serialize_Deserialize_With_Nullable_Enum()
{ {
var json = "{\"name\":\"abp\",\"type\":null}"; var json = "{\"name\":\"abp\",\"type\":null}";
var file = _jsonSerializer.Deserialize<FileWithNullableEnum>(json); var file = JsonSerializer.Deserialize<FileWithNullableEnum>(json);
file.Name.ShouldBe("abp"); file.Name.ShouldBe("abp");
file.Type.ShouldBeNull(); file.Type.ShouldBeNull();
var newJson = _jsonSerializer.Serialize(file); var newJson = JsonSerializer.Serialize(file);
newJson.ShouldBe("{\"name\":\"abp\",\"type\":null}"); newJson.ShouldBe("{\"name\":\"abp\",\"type\":null}");
json = "{\"name\":\"abp\",\"type\":\"Exe\"}"; json = "{\"name\":\"abp\",\"type\":\"Exe\"}";
file = _jsonSerializer.Deserialize<FileWithNullableEnum>(json); file = JsonSerializer.Deserialize<FileWithNullableEnum>(json);
file.Type.ShouldNotBeNull(); file.Type.ShouldNotBeNull();
file.Type.ShouldBe(FileType.Exe); file.Type.ShouldBe(FileType.Exe);
newJson = _jsonSerializer.Serialize(file); newJson = JsonSerializer.Serialize(file);
newJson.ShouldBe("{\"name\":\"abp\",\"type\":2}"); newJson.ShouldBe("{\"name\":\"abp\",\"type\":2}");
} }
[Fact] [Fact]
public void Serialize_Deserialize_ExtensibleObject() public void Serialize_Deserialize_ExtensibleObject()
{ {
var json = "{\"name\":\"test\",\"extraProperties\":{\"One\":\"123\",\"Two\":456}}"; var json = "{\"name\":\"test\",\"extraProperties\":{\"One\":\"123\",\"Two\":456}}";
var extensibleObject = _jsonSerializer.Deserialize<TestExtensibleObjectClass>(json); var extensibleObject = JsonSerializer.Deserialize<TestExtensibleObjectClass>(json);
extensibleObject.GetProperty("One").ShouldBe("123"); extensibleObject.GetProperty("One").ShouldBe("123");
extensibleObject.GetProperty("Two").ShouldBe(456); extensibleObject.GetProperty("Two").ShouldBe(456);
var newJson = _jsonSerializer.Serialize(extensibleObject); var newJson = JsonSerializer.Serialize(extensibleObject);
newJson.ShouldBe(json); newJson.ShouldBe(json);
} }
class TestExtensibleObjectClass : ExtensibleObject [Fact]
public void Serialize_Deserialize_ExtensibleObject_Without_String()
{ {
public string Name { get; set; } var json = "{\"name\":\"test\"}";
var extensibleObject = JsonSerializer.Deserialize<TestExtensibleObjectClass>(json);
extensibleObject.ExtraProperties.ShouldNotBeNull();
extensibleObject.ExtraProperties.ShouldBeEmpty();
} }
class FileWithBoolean [Fact]
public void Serialize_Deserialize_ExtensibleObject_Without_Empty()
{ {
public string Name { get; set; } var json = "{\"name\":\"test\",\"extraProperties\":{}}";
var extensibleObject = JsonSerializer.Deserialize<TestExtensibleObjectClass>(json);
extensibleObject.ExtraProperties.ShouldNotBeNull();
extensibleObject.ExtraProperties.ShouldBeEmpty();
}
public bool IsDeleted { get; set; } [Fact]
public void Serialize_Deserialize_ExtensibleObject_Without_Null()
{
var json = "{\"name\":\"test\",\"extraProperties\":null}";
var extensibleObject = JsonSerializer.Deserialize<TestExtensibleObjectClass>(json);
extensibleObject.ExtraProperties.ShouldNotBeNull();
extensibleObject.ExtraProperties.ShouldBeEmpty();
} }
class FileWithNullableBoolean [Fact]
public void Serialize_Deserialize_With_Datetime()
{ {
public string Name { get; set; } var json = "{\"name\":\"abp\",\"creationTime\":\"2020-11-20T00:00:00\"}";
var file = JsonSerializer.Deserialize<FileWithDatetime>(json);
file.CreationTime.Year.ShouldBe(2020);
file.CreationTime.Month.ShouldBe(11);
file.CreationTime.Day.ShouldBe(20);
public bool? IsDeleted { get; set; } var newJson = JsonSerializer.Serialize(file);
newJson.ShouldBe(json);
} }
class FileWithEnum [Fact]
public void Serialize_Deserialize_With_Nullable_Datetime()
{ {
public string Name { get; set; } var json = "{\"name\":\"abp\",\"creationTime\":null}";
var file = JsonSerializer.Deserialize<FileWithNullableDatetime>(json);
file.CreationTime.ShouldBeNull();
public FileType Type { get; set; } json = "{\"name\":\"abp\"}";
file = JsonSerializer.Deserialize<FileWithNullableDatetime>(json);
file.CreationTime.ShouldBeNull();
json = "{\"name\":\"abp\",\"creationTime\":\"2020-11-20T00:00:00\"}";
file = JsonSerializer.Deserialize<FileWithNullableDatetime>(json);
file.CreationTime.ShouldNotBeNull();
file.CreationTime.Value.Year.ShouldBe(2020);
file.CreationTime.Value.Month.ShouldBe(11);
file.CreationTime.Value.Day.ShouldBe(20);
var newJson = JsonSerializer.Serialize(file);
newJson.ShouldBe(json);
} }
}
class FileWithNullableEnum public class AbpSystemTextJsonSerializerProvider_DateTimeFormat_Tests : AbpSystemTextJsonSerializerProvider_TestBase
{
protected override void AfterAddApplication(IServiceCollection services)
{ {
public string Name { get; set; } services.Configure<AbpJsonOptions>(options =>
{
options.DefaultDateTimeFormat = "yyyy*MM*dd";
});
}
public FileType? Type { get; set; } [Fact]
public void Serialize_Deserialize_With_Format_Datetime()
{
var json = "{\"name\":\"abp\",\"creationTime\":\"2020*11*20\"}";
var file = JsonSerializer.Deserialize<FileWithDatetime>(json);
file.CreationTime.Year.ShouldBe(2020);
file.CreationTime.Month.ShouldBe(11);
file.CreationTime.Day.ShouldBe(20);
var newJson = JsonSerializer.Serialize(file);
newJson.ShouldBe(json);
} }
enum FileType [Fact]
public void Serialize_Deserialize_With_Nullable_Format_Datetime()
{ {
Zip = 0, var json = "{\"name\":\"abp\",\"creationTime\":null}";
Exe = 2 var file = JsonSerializer.Deserialize<FileWithNullableDatetime>(json);
file.CreationTime.ShouldBeNull();
json = "{\"name\":\"abp\"}";
file = JsonSerializer.Deserialize<FileWithNullableDatetime>(json);
file.CreationTime.ShouldBeNull();
json = "{\"name\":\"abp\",\"creationTime\":\"2020*11*20\"}";
file = JsonSerializer.Deserialize<FileWithNullableDatetime>(json);
file.CreationTime.ShouldNotBeNull();
file.CreationTime.Value.Year.ShouldBe(2020);
file.CreationTime.Value.Month.ShouldBe(11);
file.CreationTime.Value.Day.ShouldBe(20);
var newJson = JsonSerializer.Serialize(file);
newJson.ShouldBe(json);
} }
} }
public abstract class AbpSystemTextJsonSerializerProvider_Datetime_Kind_Tests : AbpSystemTextJsonSerializerProvider_TestBase
{
protected DateTimeKind Kind { get; set; } = DateTimeKind.Unspecified;
[Fact]
public void Serialize_Deserialize()
{
var json = "{\"name\":\"abp\",\"creationTime\":\"2020-11-20T00:00:00\"}";
var file = JsonSerializer.Deserialize<FileWithDatetime>(json);
file.CreationTime.Kind.ShouldBe(Kind);
}
}
public class AbpSystemTextJsonSerializerProvider_Datetime_Kind_UTC_Tests : AbpSystemTextJsonSerializerProvider_Datetime_Kind_Tests
{
protected override void AfterAddApplication(IServiceCollection services)
{
Kind = DateTimeKind.Utc;
services.Configure<AbpClockOptions>(x => x.Kind = Kind);
}
}
public class AbpSystemTextJsonSerializerProvider_Datetime_Kind_Local_Tests : AbpSystemTextJsonSerializerProvider_Datetime_Kind_Tests
{
protected override void AfterAddApplication(IServiceCollection services)
{
Kind = DateTimeKind.Local;
services.Configure<AbpClockOptions>(x => x.Kind = Kind);
}
}
public class AbpSystemTextJsonSerializerProvider_Datetime_Kind_Unspecified_Tests : AbpSystemTextJsonSerializerProvider_Datetime_Kind_Tests
{
}
} }

23
framework/test/Volo.Abp.MemoryDb.Tests/Volo/Abp/MemoryDb/JsonConverters/EntityJsonConverter.cs

@ -6,21 +6,28 @@ using Volo.Abp.Domain.Entities;
namespace Volo.Abp.MemoryDb.JsonConverters namespace Volo.Abp.MemoryDb.JsonConverters
{ {
public class EntityJsonConverter<TEntity, TKey> : JsonConverter<TEntity> public class EntityJsonConverter<TEntity, TKey> : JsonConverter<TEntity>
where TEntity : IEntity<TKey> where TEntity : Entity<TKey>
{ {
public override TEntity Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) public override TEntity Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{ {
var jsonDocument = JsonDocument.ParseValue(ref reader); var jsonDocument = JsonDocument.ParseValue(ref reader);
var entity = (TEntity)JsonSerializer.Deserialize(jsonDocument.RootElement.GetRawText(), typeToConvert); if (jsonDocument.RootElement.ValueKind == JsonValueKind.Object)
var idJsonElement = jsonDocument.RootElement.GetProperty(nameof(IEntity<object>.Id));
var id = JsonSerializer.Deserialize<TKey>(idJsonElement.GetRawText());
if (id != null)
{ {
EntityHelper.TrySetId(entity, () => id); var entity = (TEntity)JsonSerializer.Deserialize(jsonDocument.RootElement.GetRawText(), typeToConvert);
var idJsonElement = jsonDocument.RootElement.GetProperty(nameof(Entity<object>.Id));
if (idJsonElement.ValueKind != JsonValueKind.Undefined)
{
var id = JsonSerializer.Deserialize<TKey>(idJsonElement.GetRawText());
if (id != null)
{
EntityHelper.TrySetId(entity, () => id);
}
}
return entity;
} }
return entity; throw new JsonException("RootElement's ValueKind is not Object!");
} }
public override void Write(Utf8JsonWriter writer, TEntity value, JsonSerializerOptions options) public override void Write(Utf8JsonWriter writer, TEntity value, JsonSerializerOptions options)

21
modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/SelectionStringValueItemSourceJsonConverter.cs

@ -1,5 +1,4 @@
using System; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text.Json; using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
@ -11,16 +10,22 @@ namespace Volo.Abp.FeatureManagement.JsonConverters
{ {
public override ISelectionStringValueItemSource Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) 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 rootElement = JsonDocument.ParseValue(ref reader).RootElement;
var items = rootElement.EnumerateObject().FirstOrDefault(x => x.Name.Equals(nameof(ISelectionStringValueItemSource.Items), StringComparison.OrdinalIgnoreCase)).Value.GetRawText(); var itemsJsonProperty = rootElement.EnumerateObject().FirstOrDefault(x =>
x.Name.Equals(nameof(ISelectionStringValueItemSource.Items), StringComparison.OrdinalIgnoreCase));
if (itemsJsonProperty.Value.ValueKind == JsonValueKind.Array)
{
var newOptions = JsonSerializerOptionsHelper.Create(options, this);
var selectionStringValueItem =
JsonSerializer.Deserialize<LocalizableSelectionStringValueItem[]>(itemsJsonProperty.Value.GetRawText(), newOptions) ??
Array.Empty<LocalizableSelectionStringValueItem>();
var selectionStringValueItem = return new StaticSelectionStringValueItemSource(selectionStringValueItem.As<ISelectionStringValueItem[]>());
JsonSerializer.Deserialize<List<LocalizableSelectionStringValueItem>>(items, newOptions) ?? }
new List<LocalizableSelectionStringValueItem>();
return new StaticSelectionStringValueItemSource(selectionStringValueItem.ToArray().As<ISelectionStringValueItem[]>()); throw new JsonException($"Can't to get the {nameof(ISelectionStringValueItemSource.Items)} property of {nameof(ISelectionStringValueItemSource)}!");
} }
public override void Write(Utf8JsonWriter writer, ISelectionStringValueItemSource value, JsonSerializerOptions options) public override void Write(Utf8JsonWriter writer, ISelectionStringValueItemSource value, JsonSerializerOptions options)

26
modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/StringValueTypeJsonConverter.cs

@ -11,15 +11,25 @@ namespace Volo.Abp.FeatureManagement.JsonConverters
public override IStringValueType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) public override IStringValueType Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{ {
var rootElement = JsonDocument.ParseValue(ref reader).RootElement; var rootElement = JsonDocument.ParseValue(ref reader).RootElement;
var name = rootElement.EnumerateObject().FirstOrDefault(x => x.Name.Equals(nameof(IStringValueType.Name), StringComparison.OrdinalIgnoreCase)).Value.GetString();
var newOptions = JsonSerializerOptionsHelper.Create(options, this, new ValueValidatorJsonConverter(), new SelectionStringValueItemSourceJsonConverter()); var nameJsonProperty = rootElement.EnumerateObject().FirstOrDefault(x => x.Name.Equals(nameof(IStringValueType.Name), StringComparison.OrdinalIgnoreCase));
return name switch if (nameJsonProperty.Value.ValueKind == JsonValueKind.String)
{ {
"SelectionStringValueType" => JsonSerializer.Deserialize<SelectionStringValueType>(rootElement.GetRawText(), newOptions), var name = nameJsonProperty.Value.GetString();
"FreeTextStringValueType" => JsonSerializer.Deserialize<FreeTextStringValueType>(rootElement.GetRawText(), newOptions),
"ToggleStringValueType" => JsonSerializer.Deserialize<ToggleStringValueType>(rootElement.GetRawText(), newOptions), var newOptions = JsonSerializerOptionsHelper.Create(options, this, new ValueValidatorJsonConverter(),
_ => throw new ArgumentException($"{nameof(IStringValueType)} named {name} was not found!") 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!")
};
}
throw new JsonException($"Can't to get the {nameof(IStringValueType.Name)} property of {nameof(IStringValueType)}!");
} }
public override void Write(Utf8JsonWriter writer, IStringValueType value, JsonSerializerOptions options) public override void Write(Utf8JsonWriter writer, IStringValueType value, JsonSerializerOptions options)

27
modules/feature-management/src/Volo.Abp.FeatureManagement.Application.Contracts/Volo/Abp/FeatureManagement/JsonConverters/ValueValidatorJsonConverter.cs

@ -13,21 +13,30 @@ namespace Volo.Abp.FeatureManagement.JsonConverters
public override IValueValidator Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) public override IValueValidator Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{ {
var rootElement = JsonDocument.ParseValue(ref reader).RootElement; var rootElement = JsonDocument.ParseValue(ref reader).RootElement;
var name = rootElement.EnumerateObject().FirstOrDefault(x => x.Name.Equals(nameof(IValueValidator.Name), StringComparison.OrdinalIgnoreCase)).Value.GetString();
var valueValidator = CreateValueValidatorByName(name);
var propertiesRawText = rootElement.EnumerateObject().FirstOrDefault(x => x.Name.Equals(nameof(IValueValidator.Properties), StringComparison.OrdinalIgnoreCase)).Value.GetRawText(); var nameJsonProperty = rootElement.EnumerateObject().FirstOrDefault(x => x.Name.Equals(nameof(IValueValidator.Name), StringComparison.OrdinalIgnoreCase));
var newOptions = JsonSerializerOptionsHelper.Create(options, this, new ObjectToInferredTypesConverter()); if (nameJsonProperty.Value.ValueKind == JsonValueKind.String)
var properties = JsonSerializer.Deserialize<IDictionary<string, object>>(propertiesRawText, newOptions);
if (properties != null && properties.Any())
{ {
foreach (var property in properties) var valueValidator = CreateValueValidatorByName(nameJsonProperty.Value.GetString());
var propertiesJsonProperty = rootElement.EnumerateObject().FirstOrDefault(x => x.Name.Equals(nameof(IValueValidator.Properties), StringComparison.OrdinalIgnoreCase));
if (propertiesJsonProperty.Value.ValueKind == JsonValueKind.Object)
{ {
valueValidator.Properties[property.Key] = property.Value; var newOptions = JsonSerializerOptionsHelper.Create(options, this, new ObjectToInferredTypesConverter());
var properties = JsonSerializer.Deserialize<IDictionary<string, object>>(propertiesJsonProperty.Value.GetRawText(), newOptions);
if (properties != null && properties.Any())
{
foreach (var property in properties)
{
valueValidator.Properties[property.Key] = property.Value;
}
}
} }
return valueValidator;
} }
return valueValidator; throw new JsonException($"Can't to get the {nameof(IValueValidator.Name)} property of {nameof(IValueValidator)}!");
} }
public override void Write(Utf8JsonWriter writer, IValueValidator value, JsonSerializerOptions options) public override void Write(Utf8JsonWriter writer, IValueValidator value, JsonSerializerOptions options)

11
modules/feature-management/test/Volo.Abp.FeatureManagement.Application.Tests/Volo/Abp/FeatureManagement/StringValueJsonConverter_Tests.cs

@ -60,6 +60,14 @@ namespace Volo.Abp.FeatureManagement
MinValue = 10 MinValue = 10
} }
} }
},
new FeatureDto
{
Provider = new FeatureProviderDto
{
Name = "FeatureName",
Key = "FeatureKey"
}
} }
} }
} }
@ -85,6 +93,9 @@ namespace Volo.Abp.FeatureManagement
featureListDto2.Groups[0].Features[2].ValueType.Validator.ShouldBeOfType<NumericValueValidator>(); featureListDto2.Groups[0].Features[2].ValueType.Validator.ShouldBeOfType<NumericValueValidator>();
featureListDto2.Groups[0].Features[2].ValueType.Validator.As<NumericValueValidator>().MaxValue.ShouldBe(1000); featureListDto2.Groups[0].Features[2].ValueType.Validator.As<NumericValueValidator>().MaxValue.ShouldBe(1000);
featureListDto2.Groups[0].Features[2].ValueType.Validator.As<NumericValueValidator>().MinValue.ShouldBe(10); featureListDto2.Groups[0].Features[2].ValueType.Validator.As<NumericValueValidator>().MinValue.ShouldBe(10);
featureListDto2.Groups[0].Features[3].Provider.Name.ShouldBe("FeatureName");
featureListDto2.Groups[0].Features[3].Provider.Key.ShouldBe("FeatureKey");
} }
} }
} }

Loading…
Cancel
Save