gpt4 book ai didi

c# - 反序列化实现 IEnumerable 的类

转载 作者:行者123 更新时间:2023-12-05 05:30:34 26 4
gpt4 key购买 nike

我开发了一个小程序,允许在 Json 中序列化/反序列化一个类。

这个程序,我把它做成 .NET 7,因此我使用 System.Text.Json

所以我有一个 ITest 接口(interface)。该接口(interface)在两个类 TestSuite 和 TestCase 中实现。

[JsonDerivedType(typeof(TestSuite), "testSuite")]
[JsonDerivedType(typeof(TestCase), "testCase")]
[JsonPolymorphic(UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToNearestAncestor)]
public interface ITest
{
}
public class TestCase : ITest
{
public string Name { get; set; }
}
public class TestSuite : ITest, IEnumerable<ITest>
{
private readonly List<ITest> _tests = new ();

public void Add(ITest test)
{
_tests.Add(test);
}

/// <inheritdoc />
public IEnumerator<ITest> GetEnumerator()
{
return _tests.GetEnumerator();
}

/// <inheritdoc />
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}

为了测试,我这样做:

ITest suite = new TestSuite { new TestCase { Name = "Oui" }, new TestCase { Name = "Test2" } };

string json = JsonSerializer.Serialize(suite);

var s = JsonSerializer.Deserialize<ITest>(json);

Console.WriteLine(json);

TestCase 序列化和反序列化工作完美。

但对于 TestSuite 反序列化失败并显示错误消息:

System.NotSupportedException: 'The collection type 'Test.TestSuite' is abstract, an interface, or is read only, and could not be instantiated and populated. Path: $.$values ​​| LineNumber: 0 | BytePositionInLine: 32.'

我不能使用自定义的JsonConverter,因为json多态默认只支持json转换器。

你知道我怎么解决这个问题吗?

提前致谢

我尝试为 TestSuite 创建自定义 JsonConverter,但我做不到。然后我尝试中止 json 多态性并为 ITest 创建自定义 JsonConverter 但这不是一个好主意。

最佳答案

这里的问题是你的类实现了一个集合接口(interface),而 ATM 没有构建方式来告诉 System.Text.Json将您的对象序列化为对象,而不是集合(跟踪 this one 以了解何时可能)。

如果您真的-真的需要使用当前的类结构,您可以进入反射的兔子洞并弄乱 System.Text.Json内部结构(请注意,这可能非常脆弱):

// tells to serialize `TestSuite` as object
internal sealed class ObjectConverterFactory : JsonConverterFactory
{
public override bool CanConvert(Type typeToConvert)
{
return typeToConvert == typeof(TestSuite);
}

public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options)
{
var type = typeof(JsonConverterFactory).Assembly.GetType("System.Text.Json.Serialization.Converters.ObjectConverterFactory");
var f = (JsonConverterFactory)Activator.CreateInstance(type, new object[]{true});
return f.CreateConverter(typeToConvert, options);
}
}

// exposes private property to serializer
static void Test(JsonTypeInfo jsonTypeInfo)
{
if (jsonTypeInfo.Type == typeof(TestSuite))
{
var field = typeof(TestSuite).GetField("_tests", BindingFlags.Instance | BindingFlags.NonPublic);
JsonPropertyInfo jsonPropertyInfo = jsonTypeInfo.CreateJsonPropertyInfo(field.FieldType, field.Name);
jsonPropertyInfo.Get = field.GetValue;
jsonPropertyInfo.Set = field.SetValue;
jsonTypeInfo.Properties.Add(jsonPropertyInfo);
}
}

和用法:

ITest suite = new TestSuite { new TestCase { Name = "Oui" }, new TestCase { Name = "Test2" } };

var jsonSerializerOptions = new JsonSerializerOptions
{
Converters = { new ObjectConverterFactory() },
TypeInfoResolver = new DefaultJsonTypeInfoResolver
{
Modifiers = { Test }
}
};
string json1 = JsonSerializer.Serialize(suite, jsonSerializerOptions);

var s = JsonSerializer.Deserialize<ITest>(json1, jsonSerializerOptions);

再次注意,这可能非常脆弱(主要是由于 ObjectConverterFactory 的实现),我建议删除 IEnumerable<ITest>来自 TestSuite .

关于c# - 反序列化实现 IEnumerable 的类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74622159/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com