C# Can';t将JSON反序列化为具有嵌套列表的对象

C# Can';t将JSON反序列化为具有嵌套列表的对象,c#,json,firebase,deserialization,fire-sharp,C#,Json,Firebase,Deserialization,Fire Sharp,很抱歉,我问了一个相当常见的问题,我已经到处找了,找不到解决问题的方法 我正在使用Firesharp,并尝试反序列化Firebase返回到具有嵌套列表的类中的Json对象 public class Class { public string Name { get; set; } public string Desc { get; set; } public string HPDie { get; set; } public

很抱歉,我问了一个相当常见的问题,我已经到处找了,找不到解决问题的方法

我正在使用Firesharp,并尝试反序列化Firebase返回到具有嵌套列表的类中的Json对象

public class Class
    {
        public string Name { get; set; }
        public string Desc { get; set; }
        public string HPDie { get; set; }
        public string Role { get; set; }
        public int RPL { get; set; }
        public IList<Level> Levels { get; set; }

        public Class() { }
        public Class(string name, string desc, string hpdie, string role, int rPL, List<Level> levels) 
        {
            Name = name;
            Desc = desc;
            HPDie = hpdie;
            RPL = rPL;
            Levels = levels;
        }
    }

这决不是一个完整的答案。我假设您不想为每个“子类”(例如Barbarian、Wizard等)映射/创建类。您可以使用JsonConverter。该示例仅处理第一个“匿名”对象范围。也许你会发现其中一些有用

var result = JsonConvert.DeserializeObject<Response>(jsonInput);
var result=JsonConvert.DeserializeObject(jsonInput);
公共类类JsonConverter:JsonConverter
{
公共重写对象ReadJson(JsonReader阅读器,类型objectType,对象existingValue,JsonSerializer序列化程序)
{
返回新类
{
ClassSpecifics=JObject.Load(reader).Values().Select(x=>x.ToObject()).ToList()
};
}
public override void WriteJson(JsonWriter writer,object value,JsonSerializer serializer){throw new NotImplementedException();}
public override bool CanConvert(类型objectType){throw new NotImplementedException();}
}
公众课堂反应
{
公共类{get;set;}
}
[JsonConverter(类型(ClassJsonConverter))]
公共课
{
公共列表类详细信息{get;set;}
}
公共类详细信息
{
公共字符串名称{get;set;}
公共字符串Desc{get;set;}
公共字符串HPDie{get;set;}
公共字符串角色{get;set;}
公共int RPL{get;set;}
}

如果您还添加了要反序列化的json,那么它确实很有帮助,因此我所说的一切都是基于对未提供的json的假设。也就是说,这似乎是一个常见的错误。您要求它反序列化一个
IEnumerable
(因此,一个json数组以
[
开始,以
]
结束,您可能已经为它提供了一个实例(以
{
开始,以
}
结束)。因此,要么修复json(只需在现有的内容周围添加
[]
)或者将反序列化更改为此
Class data=JsonConvert.DeserializeObject(res.Body);
。抱歉,添加了Json。提供了两种解决方案,添加了[]将类转换为数组或更改代码似乎可以解决问题。您的类结构对于json来说是完全错误的。
class
没有名称、描述、hpdie等。Barbarian和Wizard有。您可能希望使用visual studio的粘贴json作为类来自动生成类,然后你可以根据需要修改它们。恐怕我不明白,对不起。我想做的是填写一张包含类详细信息的表单,然后将其上传到Firebase,刷新程序中的列表,在其中我可以选择类的名称,让其详细信息填充表单,包括另外两个级别和技能列表如果我这样做了,我将无法添加新类,对吗?因为我也需要在代码中创建一个新类。首先,我的原始注释是正确的,但是因为有更多的问题,在修复后它仍然不起作用(请记住,虽然它修复了所描述的问题,但只是出现了一个新问题,我的假设是您会收到一条稍微不同的异常消息)。正如@Crowcoder所说,您的模型不适合您的json。在您的json中,您的
包含两个属性:
Barbarian
Wizard
。此结构未反映在您的模型中,因此无法转换。请尝试使用类似工具查看json的结构。非常感谢。
private async void RefreshClasses()
    {
        this.classList = new List<Class>();
        FirebaseResponse res = await client.GetAsync("Class");

        IEnumerable<Class> data = JsonConvert.DeserializeObject<IEnumerable<Class>>(res.Body);

        if (data != null)
        {
            PopulateDGVClasses(data);
        }
    }
    {
  "Class" : {
    "Barbarian" : {
      "Desc" : "Barbarians excel in combat, possessing the martial prowess and fortitude to take on foes seemingly far superior to themselves. With rage granting them boldness and daring beyond that of most other warriors, barbarians charge furiously into battle and ruin all who would stand in their way.",
      "HPDie" : "d12",
      "Levels" : [ {
        "BAB" : 2,
        "FortSave" : 2,
        "Number" : 1,
        "RexSave" : 0,
        "Skills" : {
          "Prueba" : {
            "Desc" : "Probota"
          }
        },
        "SpellsKnown" : 0,
        "WillSave" : 0
      }, {
        "BAB" : 3,
        "FortSave" : 3,
        "Number" : 2,
        "RexSave" : 0,
        "SpellsKnown" : 0,
        "WillSave" : 0
      }, {
        "BAB" : 3,
        "FortSave" : 3,
        "Number" : 3,
        "RexSave" : 1,
        "SpellsKnown" : 0,
        "WillSave" : 1
      }, {
        "BAB" : 4,
        "FortSave" : 4,
        "Number" : 4,
        "RexSave" : 1,
        "SpellsKnown" : 0,
        "WillSave" : 1
      }, {
        "BAB" : 5,
        "FortSave" : 4,
        "Number" : 5,
        "RexSave" : 1,
        "SpellsKnown" : 0,
        "WillSave" : 1
      }, {
        "BAB" : 6,
        "FortSave" : 5,
        "Number" : 6,
        "RexSave" : 2,
        "SpellsKnown" : 0,
        "WillSave" : 2
      }, {
        "BAB" : 7,
        "FortSave" : 5,
        "Number" : 7,
        "RexSave" : 2,
        "SpellsKnown" : 0,
        "WillSave" : 2
      }, {
        "BAB" : 8,
        "FortSave" : 6,
        "Number" : 8,
        "RexSave" : 2,
        "SpellsKnown" : 0,
        "WillSave" : 2
      }, {
        "BAB" : 9,
        "FortSave" : 6,
        "Number" : 9,
        "RexSave" : 3,
        "SpellsKnown" : 0,
        "WillSave" : 3
      }, {
        "BAB" : 10,
        "FortSave" : 7,
        "Number" : 10,
        "RexSave" : 3,
        "SpellsKnown" : 0,
        "WillSave" : 3
      } ],
      "Name" : "Barbarian",
      "RPL" : 4
    },
    "Wizard" : {
      "Desc" : "While universalist wizards might study to prepare themselves for any manner of danger, specialist wizards research schools of magic that make them exceptionally skilled within a specific focus. \r\n\r\nYet no matter their specialty, all wizards are masters of the impossible and can aid their allies in overcoming any danger.",
      "HPDie" : "d6",
      "Levels" : [ {
        "BAB" : 0,
        "FortSave" : 0,
        "Number" : 1,
        "RexSave" : 0,
        "SpellsKnown" : 4,
        "WillSave" : 2
      }, {
        "BAB" : 1,
        "FortSave" : 0,
        "Number" : 2,
        "RexSave" : 0,
        "SpellsKnown" : 6,
        "WillSave" : 3
      }, {
        "BAB" : 1,
        "FortSave" : 1,
        "Number" : 3,
        "RexSave" : 1,
        "SpellsKnown" : 7,
        "WillSave" : 3
      }, {
        "BAB" : 2,
        "FortSave" : 1,
        "Number" : 4,
        "RexSave" : 1,
        "SpellsKnown" : 9,
        "WillSave" : 4
      }, {
        "BAB" : 2,
        "FortSave" : 1,
        "Number" : 5,
        "RexSave" : 1,
        "SpellsKnown" : 10,
        "WillSave" : 4
      }, {
        "BAB" : 3,
        "FortSave" : 2,
        "Number" : 6,
        "RexSave" : 2,
        "SpellsKnown" : 12,
        "WillSave" : 5
      }, {
        "BAB" : 3,
        "FortSave" : 2,
        "Number" : 7,
        "RexSave" : 2,
        "SpellsKnown" : 14,
        "WillSave" : 5
      }, {
        "BAB" : 4,
        "FortSave" : 2,
        "Number" : 8,
        "RexSave" : 2,
        "SpellsKnown" : 16,
        "WillSave" : 6
      }, {
        "BAB" : 4,
        "FortSave" : 3,
        "Number" : 9,
        "RexSave" : 3,
        "SpellsKnown" : 18,
        "WillSave" : 6
      }, {
        "BAB" : 5,
        "FortSave" : 3,
        "Number" : 10,
        "RexSave" : 3,
        "SpellsKnown" : 20,
        "WillSave" : 7
      } ],
      "Name" : "Wizard",
      "RPL" : 2
    }
  },
  "Equipment" : {
    "Battleaxe" : {
      "ACBonus" : 0,
      "ACType" : "(None)",
      "Blunt" : false,
      "Bonus" : "",
      "Category" : "Weapon",
      "Cost" : "10gp",
      "DMG_Large" : "1d10",
      "DMG_Medium" : "1d8",
      "DMG_Small" : "1d6",
      "Description" : "The handle of this axe is long enough that you can wield it one-handed or two-handed. The head may have one blade or two, with blade shapes ranging from half-moons to squared edges like narrower versions of woodcutting axes. The wooden haft may be protected and strengthened with metal bands called langets.",
      "Name" : "Battleaxe",
      "Penetrating" : false,
      "Range" : "",
      "Slashing" : true,
      "Throwable" : false
    },
    "Composite Longbow" : {
      "ACBonus" : 0,
      "ACType" : "(None)",
      "Blunt" : false,
      "Bonus" : "If your STR is equal or more than the rating, add your STR bonus to damage made with this weapon.",
      "Category" : "Weapon",
      "Cost" : "100gp",
      "DMG_Large" : "1d10",
      "DMG_Medium" : "1d8",
      "DMG_Small" : "1d6",
      "Description" : "You need at least two hands to use a bow, regardless of its size. You can use a composite longbow while mounted.",
      "Name" : "Composite Longbow",
      "Penetrating" : true,
      "Range" : "110ft",
      "Slashing" : false,
      "Throwable" : false
    },
    "Dagger" : {
      "ACBonus" : 0,
      "ACType" : "(None)",
      "Blunt" : false,
      "Bonus" : "+2 to Steal rolls made to hide this weapon.",
      "Category" : "Weapon",
      "Cost" : "6gp",
      "DMG_Large" : "1d6",
      "DMG_Medium" : "1d4",
      "DMG_Small" : "1d3",
      "Description" : "A one handed broad blade, shorter than a shortsword yet longer than a knife.",
      "Name" : "Dagger",
      "Penetrating" : true,
      "Range" : "10ft",
      "Slashing" : true,
      "Throwable" : true
    },
    "Shield" : {
      "ACBonus" : 2,
      "ACType" : "Light",
      "Blunt" : true,
      "Bonus" : "",
      "Category" : "Armor",
      "Cost" : "12gp",
      "DMG_Large" : "1d6",
      "DMG_Medium" : "1d4",
      "DMG_Small" : "1d2",
      "Description" : "Made of leather.",
      "Name" : "Shield",
      "Penetrating" : false,
      "Range" : "",
      "Slashing" : false,
      "Throwable" : false
    },
    "Sword" : {
      "ACBonus" : 0,
      "ACType" : "(None)",
      "Blunt" : false,
      "Bonus" : "",
      "Category" : "Weapon",
      "Cost" : "15gp",
      "DMG_Large" : "1d10",
      "DMG_Medium" : "1d8",
      "DMG_Small" : "1d6",
      "Description" : "This sword is about three and a half feet in length.",
      "Name" : "Sword",
      "Penetrating" : false,
      "Range" : "",
      "Slashing" : true,
      "Throwable" : false
    }
  },
  "Feat" : {
    "Acrobatic" : {
      "Desc" : "+2 to all of your Acrobatic rolls per each five character levels.",
      "Name" : "Acrobatic",
      "PreReq" : [ "" ],
      "Type" : "General"
    },
    "Agile Maiden" : {
      "Desc" : "For the purpose of class features (such as a ranger’s combat style, a barbarian’s fast movement, or a magus’s spellcasting), you treat Gray Maiden plate as medium armor or heavy armor, whichever is more beneficial to a given ability. This does not affect the armor’s statistics, and it is still considered heavy armor for all other purposes",
      "Name" : "Agile Maiden",
      "PreReq" : [ "Str 13", "Dex 13" ],
      "Type" : "Combat"
    }
  },
  "Spell" : {
    "Cure Minor Wounds" : {
      "CastingTime" : "None.",
      "Desc" : "When laying your hand upon a living creature, you channel positive energy that cures 1d8 points of damage +1 point per caster level (maximum +5). Since undead are powered by negative energy, this spell deals damage to them instead of curing their wounds. An undead creature can apply Spell Resistance, and can attempt a Will save to take half damage.",
      "Duration" : "Instantaneous.",
      "FortRes" : false,
      "Name" : "Cure Minor Wounds",
      "PreReq" : [ "1 Divine" ],
      "RexRes" : false,
      "School" : "Conjuration",
      "Target" : "Touched Creature.",
      "WillRes" : true
    },
    "Magic Missile" : {
      "CastingTime" : "None.",
      "Desc" : "A missile of magical energy darts forth from your fingertip and strikes its target, dealing 1d4+1 points of force damage.\r\n\r\nThe missile strikes unerringly, even if the target is in melee combat, so long as it has less than total cover or total concealment. Specific parts of a creature can’t be singled out. Objects are not damaged by the spell.\r\n\r\nFor every two caster levels beyond 1st, you gain an additional missile – two at 3rd level, three at 5th, four at 7th, and the maximum of five missiles at 9th level or higher. If you shoot multiple missiles, you can have them strike a single creature or several creatures. A single missile can strike only one creature. You must designate targets before you check for spell resistance or roll damage.",
      "Duration" : "Instantaneous.",
      "FortRes" : false,
      "Name" : "Magic Missile",
      "PreReq" : [ "1 Divine\r\n1 Arcane\r\n1 Divine\r\n1 Arcane\r\n1 Divine\r\n1 Arcane\r\n" ],
      "RexRes" : false,
      "School" : "Evocation",
      "Target" : "Up to five none of which can be separated by more than 15 ft.",
      "WillRes" : false
    }
  }
}
var result = JsonConvert.DeserializeObject<Response>(jsonInput);
public class ClassJsonConverter : JsonConverter
{
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        return new Class
        {
            ClassSpecifics = JObject.Load(reader).Values().Select(x => x.ToObject<ClassSpecifics>()).ToList()
        };
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { throw new NotImplementedException(); }   
    public override bool CanConvert(Type objectType) { throw new NotImplementedException(); }
}

public class Response
{
    public Class Class { get; set; }
}

[JsonConverter(typeof(ClassJsonConverter))]
public class Class
{
    public List<ClassSpecifics> ClassSpecifics { get; set; }
}

public class ClassSpecifics
{
    public string Name { get; set; }
    public string Desc { get; set; }
    public string HPDie { get; set; }
    public string Role { get; set; }
    public int RPL { get; set; }
}