【发布时间】:2022-01-11 07:59:01
【问题描述】:
我用 .NET 6 编写了一个测试程序
static void Main(string[] args) {
JsonSerializerOptions options = new JsonSerializerOptions() {
Converters = {
new JsonStringEnumConverter(),
new JsonStringAbilityEffectFactoryConverter()
}
};
AbilityTemplate dictionary = JsonSerializer.Deserialize<AbilityTemplate>(@"
{
""Id"": ""StandardShot"",
""Price"": 10,
""Size"": 1,
""Rarity"": ""Common"",
""AbilityEffectFactory"": {
""Id"":""StandardShotEffectFactory""
},
""PropertyBasicValues"": {
""CoolDownRate"": 5,
""CastRate"": ""Infinity""
}
}
");
}
}
internal class JsonStringAbilityEffectFactoryConverter : JsonConverter<AbilityEffectFactory> {
public override AbilityEffectFactory Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {
string id = "";//Break point here. This method is just casually implemented because I am merely especting this method to be called.
while (reader.Read()) {
id = reader.GetString();
}
return AbilityEffectFactory.Dictionary[id];
}
public override void Write(Utf8JsonWriter writer, AbilityEffectFactory value, JsonSerializerOptions options) {
throw new NotImplementedException();
}
}
而我的 AbilityTemplate 类是这样的:
public class AbilityTemplate : RarityObject {
public AbilityTemplate(string id, int price, int size, Rarity rarity, AbilityEffectFactory abilityEffectFactory, in Ability.PropertyCollection propertyBasicValues) {
Id = id;
Price = price;
Size = size;
Rarity = rarity;
AbilityEffectFactory = abilityEffectFactory;
PropertyBasicValues = propertyBasicValues;
}
internal static readonly Dictionary<string, AbilityTemplate> dictionary = new Dictionary<string, AbilityTemplate>();
public static IReadOnlyDictionary<string, AbilityTemplate> Dictionary => dictionary;
public string Id { get; }
public int Price { get; }
public override Rarity Rarity { get; }
public int Size { get; }
public AbilityEffectFactory AbilityEffectFactory { get; }
public Ability.PropertyCollection PropertyBasicValues { get; }
}
父类 RarityObject 只是一个简单的抽象类,其中一个字段被覆盖:
public abstract class RarityObject {
public abstract Rarity Rarity { get; }
}
但是,当代码执行时,我被抛出了异常:
System.InvalidOperationException: 'Enigma.Game.AbilityTemplate' 类型的反序列化构造函数中的每个参数都必须绑定到反序列化时的对象属性或字段。每个参数名称必须与对象上的属性或字段匹配。匹配可以不区分大小写。'
我无法理解这个异常是如何发生的。用 Json 文本编写的每个字段都已经与我的 AbilityTemplate 类的属性完全匹配。
更新0 我的 AbilityEffectFactory 是一个抽象类,也许这就是问题所在。
更新1 我将转换器修改为这样:
internal class JsonStringAbilityTemplateConverter : JsonConverter<AbilityTemplate> {
public override AbilityTemplate Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) {
string id = "";//Break point
while (reader.Read()) {
id = reader.GetString();
}
return new AbilityTemplate();
}
public override void Write(Utf8JsonWriter writer, AbilityTemplate value, JsonSerializerOptions options) {
throw new NotImplementedException();
}
}
但我仍然有异常:
System.NotSupportedException: '不支持没有无参数构造函数、单一参数化构造函数或带有 'JsonConstructorAttribute' 注释的参数化构造函数的类型的反序列化。键入“Enigma.Game.AbilityEffectFactory”。路径:$.AbilityEffectFactory |行号:6 | BytePositionInLine:45。'
并且没有命中断点。系统已经读取到第 6 行,这怎么可能?
【问题讨论】:
-
如果您将所有属性的
{ get; }更改为{ get; set },是否可以解决问题? -
@LajosArpad 但是这个类应该是不可变的
-
解决问题了吗?我们应该知道添加一个 setter 是否会修复它,即使您没有将它应用于您的解决方案。
-
您使用的是哪个版本的 .net-core?看起来应该可以在 .net-core 5+ docs.microsoft.com/en-us/dotnet/standard/serialization/…
-
@LajosArpad 它不起作用
标签: c# json .net system.text.json