Browse Source

Add `JsonInclude` to `ExtensibleObject ` & Remove `AbpHasExtraPropertiesJsonConverter`.

pull/10775/head
maliming 5 years ago
parent
commit
dfe75c2a1d
No known key found for this signature in database GPG Key ID: 96224957E51C89E
  1. 1
      framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpJsonOptionsSetup.cs
  2. 1
      framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/AbpSystemTextJsonSerializerOptionsSetup.cs
  3. 56
      framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpHasExtraPropertiesJsonConverter.cs
  4. 65
      framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpHasExtraPropertiesJsonConverterFactory.cs
  5. 2
      framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ExtensibleObject.cs
  6. 3
      framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpSystemTextJsonSerializerProvider_Tests.cs
  7. 45
      framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/ExtensibleObject_Tests.cs

1
framework/src/Volo.Abp.AspNetCore.Mvc/Volo/Abp/AspNetCore/Mvc/Json/AbpJsonOptionsSetup.cs

@ -29,7 +29,6 @@ namespace Volo.Abp.AspNetCore.Mvc.Json
options.JsonSerializerOptions.Converters.Add(new AbpStringToBooleanConverter());
options.JsonSerializerOptions.Converters.Add(new ObjectToInferredTypesConverter());
options.JsonSerializerOptions.Converters.Add(new AbpHasExtraPropertiesJsonConverterFactory());
}
}
}

1
framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/AbpSystemTextJsonSerializerOptionsSetup.cs

@ -25,7 +25,6 @@ namespace Volo.Abp.Json.SystemTextJson
options.JsonSerializerOptions.Converters.Add(new AbpStringToBooleanConverter());
options.JsonSerializerOptions.Converters.Add(new ObjectToInferredTypesConverter());
options.JsonSerializerOptions.Converters.Add(new AbpHasExtraPropertiesJsonConverterFactory());
// If the user hasn't explicitly configured the encoder, use the less strict encoder that does not encode all non-ASCII characters.
options.JsonSerializerOptions.Encoder ??= JavaScriptEncoder.UnsafeRelaxedJsonEscaping;

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

@ -1,56 +0,0 @@
using System;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
using Volo.Abp.Data;
namespace Volo.Abp.Json.SystemTextJson.JsonConverters
{
public class AbpHasExtraPropertiesJsonConverter<T> : JsonConverter<T>
where T : IHasExtraProperties
{
private JsonSerializerOptions _readJsonSerializerOptions;
private JsonSerializerOptions _writeJsonSerializerOptions;
public override T Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
_readJsonSerializerOptions ??= JsonSerializerOptionsHelper.Create(options, x => x == this);
var rootElement = JsonDocument.ParseValue(ref reader).RootElement;
if (rootElement.ValueKind == JsonValueKind.Object)
{
var converterFactory = _readJsonSerializerOptions.Converters
.FirstOrDefault(x => x is AbpHasExtraPropertiesJsonConverterFactory)
.As<AbpHasExtraPropertiesJsonConverterFactory>();
T extensibleObject;
using (converterFactory != null ? converterFactory.Exclude(typeToConvert) : NullDisposable.Instance)
{
extensibleObject = rootElement.Deserialize<T>(_readJsonSerializerOptions);
}
var extraPropertiesJsonProperty = rootElement.EnumerateObject().FirstOrDefault(x => x.Name.Equals(nameof(IHasExtraProperties.ExtraProperties), StringComparison.OrdinalIgnoreCase));
if (extraPropertiesJsonProperty.Value.ValueKind == JsonValueKind.Object)
{
var extraPropertyDictionary = extraPropertiesJsonProperty.Value.Deserialize(typeof(ExtraPropertyDictionary), _readJsonSerializerOptions);
ObjectHelper.TrySetProperty(extensibleObject, x => x.ExtraProperties, () => extraPropertyDictionary);
}
return extensibleObject;
}
throw new JsonException("RootElement's ValueKind is not Object!");
}
public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
{
_writeJsonSerializerOptions ??= JsonSerializerOptionsHelper.Create(options, x =>
x == this ||
x.GetType() == typeof(AbpHasExtraPropertiesJsonConverterFactory));
JsonSerializer.Serialize(writer, value, _writeJsonSerializerOptions);
}
}
}

65
framework/src/Volo.Abp.Json/Volo/Abp/Json/SystemTextJson/JsonConverters/AbpHasExtraPropertiesJsonConverterFactory.cs

@ -1,65 +0,0 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading;
using Volo.Abp.Data;
namespace Volo.Abp.Json.SystemTextJson.JsonConverters
{
public class AbpHasExtraPropertiesJsonConverterFactory : JsonConverterFactory
{
private static readonly ConcurrentDictionary<Type, bool> CachedTypes = new ConcurrentDictionary<Type, bool>();
private readonly AsyncLocal<List<Type>> _excludeTypes = new AsyncLocal<List<Type>>();
public IDisposable Exclude(params Type[] excludeTypes)
{
var parent = _excludeTypes.Value;
_excludeTypes.Value = excludeTypes.ToList();
return new DisposeAction(() =>
{
_excludeTypes.Value = parent;
});
}
public override bool CanConvert(Type typeToConvert)
{
if (_excludeTypes.Value != null && _excludeTypes.Value.Contains(typeToConvert))
{
return false;
}
//Only for private or protected ExtraProperties.
if (typeof(IHasExtraProperties).IsAssignableFrom(typeToConvert))
{
return CachedTypes.GetOrAdd(typeToConvert, type =>
{
var property = type.GetProperty(nameof(IHasExtraProperties.ExtraProperties));
if (property != null)
{
var setMethod = property.GetSetMethod(true);
return setMethod != null && (setMethod.IsPrivate || setMethod.IsFamily);
}
return false;
});
}
return false;
}
public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options)
{
return (JsonConverter) Activator.CreateInstance(
typeof(AbpHasExtraPropertiesJsonConverter<>).MakeGenericType(typeToConvert),
BindingFlags.Instance | BindingFlags.Public,
binder: null,
null,
culture: null)!;
}
}
}

2
framework/src/Volo.Abp.ObjectExtending/Volo/Abp/ObjectExtending/ExtensibleObject.cs

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Text.Json.Serialization;
using Volo.Abp.Data;
using Volo.Abp.DynamicProxy;
@ -9,6 +10,7 @@ namespace Volo.Abp.ObjectExtending
[Serializable]
public class ExtensibleObject : IHasExtraProperties, IValidatableObject
{
[JsonInclude]
public ExtraPropertyDictionary ExtraProperties { get; protected set; }
public ExtensibleObject()

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

@ -174,8 +174,7 @@ namespace Volo.Abp.Json
{
var json = "{\"name\":\"test\",\"extraProperties\":null}";
var extensibleObject = JsonSerializer.Deserialize<TestExtensibleObjectClass>(json);
extensibleObject.ExtraProperties.ShouldNotBeNull();
extensibleObject.ExtraProperties.ShouldBeEmpty();
extensibleObject.ExtraProperties.ShouldBeNull();
}
[Fact]

45
framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/AbpHasExtraPropertiesJsonConverter_Tests.cs → framework/test/Volo.Abp.Json.Tests/Volo/Abp/Json/ExtensibleObject_Tests.cs

@ -7,11 +7,11 @@ using Xunit;
namespace Volo.Abp.Json
{
public class AbpHasExtraPropertiesJsonConverter_Tests: AbpJsonTestBase
public class ExtensibleObject_Tests: AbpJsonTestBase
{
private readonly IJsonSerializer _jsonSerializer;
public AbpHasExtraPropertiesJsonConverter_Tests()
public ExtensibleObject_Tests()
{
_jsonSerializer = GetRequiredService<IJsonSerializer>();
}
@ -60,17 +60,54 @@ namespace Volo.Abp.Json
fooDto.BarDtos.First().Name.ShouldBe("new-bar-dto");
fooDto.BarDtos.First().GetProperty("bar").ShouldBe("new-bar-value");
}
[Fact]
public void SelfReference_Test()
{
var parentNodeDto = new NodeDto
{
Name = "parentNode",
};
parentNodeDto.SetProperty("node", "parent-value");
var nodeDto = new NodeDto
{
Name = "node",
Parent = parentNodeDto
};
nodeDto.SetProperty("node", "node-value");
var json = _jsonSerializer.Serialize(nodeDto);
nodeDto = _jsonSerializer.Deserialize<NodeDto>(json);
nodeDto.ShouldNotBeNull();
nodeDto.Name.ShouldBe("node");
nodeDto.GetProperty("node").ShouldBe("node-value");
nodeDto.Parent.ShouldNotBeNull();
nodeDto.Parent.Name.ShouldBe("parentNode");
nodeDto.Parent.GetProperty("node").ShouldBe("parent-value");
}
}
public class FooDto : ExtensibleObject
class FooDto : ExtensibleObject
{
public string Name { get; set; }
public List<BarDto> BarDtos { get; set; }
}
public class BarDto : ExtensibleObject
class BarDto : ExtensibleObject
{
public string Name { get; set; }
public FooDto FooDto { get; set; }
}
class NodeDto : ExtensibleObject
{
public string Name { get; set; }
public NodeDto Parent { get; set; }
}
}
Loading…
Cancel
Save