首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >System.Text.Json,JsonConverter未调用

System.Text.Json,JsonConverter未调用
EN

Stack Overflow用户
提问于 2022-01-08 12:24:45
回答 2查看 912关注 0票数 -1

我用.NET 6编写了一个测试程序

代码语言:javascript
复制
        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课程是这样的:

代码语言:javascript
复制
    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只是一个简单的抽象类,其中有一个字段被覆盖:

代码语言:javascript
复制
    public abstract class RarityObject {
        public abstract Rarity Rarity { get; }
    }

但是,当代码执行时,我被抛出异常:

System.InvalidOperationException:“类型'Enigma.Game.AbilityTemplate‘的反序列化构造函数中的每个参数都必须绑定到反序列化时的对象属性或字段。每个参数名必须与对象上的属性或字段匹配。这场比赛可能是不敏感的。

我不明白这种异常是怎么发生的。用Json文本编写的每个字段都已经与我的AbilityTemplate类的属性完全匹配。

Update0 My AbilityEffectFactory是一个抽象类,也许这就是问题所在。

Update1 I对转换器进行了如下修改:

代码语言:javascript
复制
    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 \ LineNumber: 6\x{e76f} BytePositionInLine: 45‘

而断点不是hit.How,因为系统已经读取到第6行了,这是否是可确定的?

EN

回答 2

Stack Overflow用户

发布于 2022-01-08 14:16:45

  1. 您的类中有一个bug??稀缺性是json中的字符串,不能是稀有类属性

  1. 当您序列化一个对象时,您只需要属性getter,属性设置器可能是可选的,但是当您反序列化对象时需要一个setter,至少在Text.Json中是这样的,因为文本json没有正确地使用构造函数。您可以尝试Newtosoft.Json,因为它可以使用构造函数.

如果您想反序列化json,

  1. 绝不会使用接口或抽象类属性,因为没有人知道要使用哪个类来创建对象。一个接口或抽象类可以有数千个不同的implementations

  1. 我通过用一个具体的dictionary类替换抽象类对您的类做了一些更改。它正在使用Newtonsoft.Json。您只需用具体的类替换对象。

代码语言:javascript
复制
AbilityTemplate abilityTemplate = JsonConvert.DeserializeObject<AbilityTemplate>(json);

班级

代码语言:javascript
复制
public class AbilityTemplate 
{
    [JsonConstructor]
    public AbilityTemplate(string id, int price, int size, string rarity, Dictionary<string, object> abilityEffectFactory, in Dictionary<string,object> 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 string Rarity { get; }
    public int Size { get; }
    public Dictionary<string,object> AbilityEffectFactory { get; }
    public Dictionary<string,object> PropertyBasicValues { get; }
}

  1. IMHO,您不需要特殊的转换器。如果要将json转换为奇怪的东西,可以将所有代码放在constructor.

中。

票数 0
EN

Stack Overflow用户

发布于 2022-01-09 05:07:32

我最终通过不使用JsonConverter完成了这一任务。如下图所示,我编写了可以转换为目标类的中间类。

代码语言:javascript
复制
    public static partial class EntityLoader {
        private class AbilityTemplateJsonObject {
            public string Id { get; set; }
            public int Price { get; set; }
            public int Size { get; set; }
            public string Rarity { get; set; }
            public string AbilityEffectFactory { get; set; }
            public AbilityPropertyCollectionJsonObject PropertyBasicValues { get; set; }
            public AbilityTemplate ConvertToAbilityTemplate() {
                return new AbilityTemplate(Id, Price, Size, Enum.Parse<Rarity>(Rarity), Game.AbilityEffectFactory.Dictionary[AbilityEffectFactory], PropertyBasicValues.ConvertToAbilityPropertyCollection());
            }
        }
        private class AbilityPropertyCollectionJsonObject {
            public double Strength { get; set; }
            public double FireRate { get; set; }
            public double PerFireQuantity { get; set; }
            public double CoolDownRate { get; set; }
            public double CastRate { get; set; }
            public double Range { get; set; }
            public double ExplosionRange { get; set; }
            public double ExplosionStrength { get; set; }
            public double ManaConservation { get; set; }
            public double ManaStorage { get; set; }
            public Ability.PropertyCollection ConvertToAbilityPropertyCollection() {
                return new Ability.PropertyCollection() {
                    [Ability.PropertyType.Strength] = Strength,
                    [Ability.PropertyType.FireRate] = FireRate,
                    [Ability.PropertyType.PerFireQuantity] = PerFireQuantity,
                    [Ability.PropertyType.CoolDownRate] = CoolDownRate,
                    [Ability.PropertyType.CastRate] = CastRate,
                    [Ability.PropertyType.Range] = Range,
                    [Ability.PropertyType.ExplosionRange] = ExplosionRange,
                    [Ability.PropertyType.ExplosionStrength] = ExplosionStrength,
                    [Ability.PropertyType.ManaConservation] = ManaConservation,
                    [Ability.PropertyType.ManaStorage] = ManaStorage
                };
            }
        }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70632275

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档