将Json字符串反序列化为复合对象时出错

本文关键字:对象 出错 复合 Json 字符串 反序列化 | 更新日期: 2023-09-27 18:08:04

我使用Newtonsoft的Json.NET。他们的文档不是很有用。

我需要的是将json字符串反序列化为我创作的类的c#对象。json字符串从来都不是这个类的对象,我使用WebRequest得到了它。

我不能发布json字符串,因为它有超过34000个字符。

由于对象使用了大量的组合,所以我尝试自己生成所需的所有类。当我得到一个FormatException"输入字符串的格式不正确。"我想一定是我的课出了问题。然后我找到了这个网站:http://json2csharp.com/

它应该为您生成所需的类,因此您可以反序列化任何json字符串。除了为同一类型(图像)生成3个不同的类外,该网站还生成了与我拥有的完全相同的类,这里和那里有不同的名称(对于类,从来没有属性)。这些是类:

public class Image
{
    public string full { get; set; }
    public string sprite { get; set; }
    public string group { get; set; }
    public int x { get; set; }
    public int y { get; set; }
    public int w { get; set; }
    public int h { get; set; }
}
public class Skin
{
    public int id { get; set; }
    public string name { get; set; }
    public int num { get; set; }
}
public class Info
{
    public int attack { get; set; }
    public int defense { get; set; }
    public int magic { get; set; }
    public int difficulty { get; set; }
}
public class Stats
{
    public double armor { get; set; }
    public int armorperlevel { get; set; }
    public int attackdamage { get; set; }
    public double attackdamageperlevel { get; set; }
    public int attackrange { get; set; }
    public double attackspeedoffset { get; set; }
    public double attackspeedperlevel { get; set; }
    public int crit { get; set; }
    public int critperlevel { get; set; }
    public int hp { get; set; }
    public int hpperlevel { get; set; }
    public double hpregen { get; set; }
    public double hpregenperlevel { get; set; }
    public int movespeed { get; set; }
    public int mp { get; set; }
    public int mpperlevel { get; set; }
    public double mpregen { get; set; }
    public double mpregenperlevel { get; set; }
    public int spellblock { get; set; }
    public int spellblockperlevel { get; set; }
}
public class Leveltip
{
    public List<string> label { get; set; }
    public List<string> effect { get; set; }
}
public class Image2
{
    public string full { get; set; }
    public string sprite { get; set; }
    public string group { get; set; }
    public int x { get; set; }
    public int y { get; set; }
    public int w { get; set; }
    public int h { get; set; }
}
public class Var
{
    public string key { get; set; }
    public string link { get; set; }
    public List<double> coeff { get; set; }
}
public class Altimage
{
    public string full { get; set; }
    public string sprite { get; set; }
    public string group { get; set; }
    public int x { get; set; }
    public int y { get; set; }
    public int w { get; set; }
    public int h { get; set; }
}
public class Spell
{
    public string name { get; set; }
    public string description { get; set; }
    public string sanitizedDescription { get; set; }
    public string tooltip { get; set; }
    public string sanitizedTooltip { get; set; }
    public Leveltip leveltip { get; set; }
    public Image2 image { get; set; }
    public string resource { get; set; }
    public int maxrank { get; set; }
    public List<int> cost { get; set; }
    public string costType { get; set; }
    public string costBurn { get; set; }
    public List<int> cooldown { get; set; }
    public string cooldownBurn { get; set; }
    public List<List<int>> effect { get; set; }
    public List<string> effectBurn { get; set; }
    public List<Var> vars { get; set; }
    public object range { get; set; }
    public string rangeBurn { get; set; }
    public string key { get; set; }
    public List<Altimage> altimages { get; set; }
}
public class Image3
{
    public string full { get; set; }
    public string sprite { get; set; }
    public string group { get; set; }
    public int x { get; set; }
    public int y { get; set; }
    public int w { get; set; }
    public int h { get; set; }
}
public class Passive
{
    public string name { get; set; }
    public string description { get; set; }
    public string sanitizedDescription { get; set; }
    public Image3 image { get; set; }
}
public class Item
{
    public int id { get; set; }
    public int count { get; set; }
}
public class Block
{
    public string type { get; set; }
    public List<Item> items { get; set; }
    public bool? recMath { get; set; }
}
public class Recommended
{
    public string champion { get; set; }
    public string title { get; set; }
    public string type { get; set; }
    public string map { get; set; }
    public string mode { get; set; }
    public bool priority { get; set; }
    public List<Block> blocks { get; set; }
}
public class RootObject
{
    public int id { get; set; }
    public string key { get; set; }
    public string name { get; set; }
    public string title { get; set; }
    public Image image { get; set; }
    public List<Skin> skins { get; set; }
    public string lore { get; set; }
    public string blurb { get; set; }
    public List<string> allytips { get; set; }
    public List<string> enemytips { get; set; }
    public List<string> tags { get; set; }
    public string partype { get; set; }
    public Info info { get; set; }
    public Stats stats { get; set; }
    public List<Spell> spells { get; set; }
    public Passive passive { get; set; }
    public List<Recommended> recommended { get; set; }
}

这是产生异常的代码:

RootObject result = JsonConvert.DeserializeObject<RootObject>(jsonString);

在那一行我仍然得到相同的FormatException。在到达异常之前,虽然我将字符串保存到一个文本文件中,然后我可以用这个软件可视化它,没有任何错误:http://jsonviewer.codeplex.com/我可以查看它的树结构和它的原始文本结构(缩进可读性),并没有任何错误的字符串。拜托,有人能帮忙吗?我不知道还能做什么。

如建议,这里是json字符串的pastebin(我第一次使用pastebin,我希望我做的一切都是正确的。顺便说一下,我把粘贴的名称打错了。应该是安妮,不是安妮。当然,这一点也不重要):http://pastebin.com/0BWimJMv

下面是异常细节:

System.FormatException was unhandled
HResult=-2146233033
Message=Input string was not in a correct format.
Source=Newtonsoft.Json
StackTrace:
   em Newtonsoft.Json.Utilities.ConvertUtils.Int32Parse(Char[] chars, Int32 start, Int32 length) na c:'Temp'Release'Working'Newtonsoft.Json'Src'Newtonsoft.Json'Utilities'ConvertUtils.cs:linha 608
   em Newtonsoft.Json.JsonTextReader.ParseNumber() na c:'Temp'Release'Working'Newtonsoft.Json'Src'Newtonsoft.Json'JsonTextReader.cs:linha 1199
   em Newtonsoft.Json.JsonTextReader.ParseValue() na c:'Temp'Release'Working'Newtonsoft.Json'Src'Newtonsoft.Json'JsonTextReader.cs:linha 1009
   em Newtonsoft.Json.JsonTextReader.ReadInternal() na c:'Temp'Release'Working'Newtonsoft.Json'Src'Newtonsoft.Json'JsonTextReader.cs:linha 383
   em Newtonsoft.Json.JsonReader.ReadAsInt32Internal() na c:'Temp'Release'Working'Newtonsoft.Json'Src'Newtonsoft.Json'JsonReader.cs:linha 577
   em Newtonsoft.Json.JsonTextReader.ReadAsInt32() na c:'Temp'Release'Working'Newtonsoft.Json'Src'Newtonsoft.Json'JsonTextReader.cs:linha 339
   em Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ReadForType(JsonReader reader, JsonContract contract, Boolean hasConverter) na c:'Temp'Release'Working'Newtonsoft.Json'Src'Newtonsoft.Json'Serialization'JsonSerializerInternalReader.cs:linha 1646
   em Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateList(IList list, JsonReader reader, JsonArrayContract contract, JsonProperty containerProperty, String id) na c:'Temp'Release'Working'Newtonsoft.Json'Src'Newtonsoft.Json'Serialization'JsonSerializerInternalReader.cs:linha 1276
   em Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateList(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue, String id) na c:'Temp'Release'Working'Newtonsoft.Json'Src'Newtonsoft.Json'Serialization'JsonSerializerInternalReader.cs:linha 644
   em Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue) na c:'Temp'Release'Working'Newtonsoft.Json'Src'Newtonsoft.Json'Serialization'JsonSerializerInternalReader.cs:linha 256
   em Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, Object target) na c:'Temp'Release'Working'Newtonsoft.Json'Src'Newtonsoft.Json'Serialization'JsonSerializerInternalReader.cs:linha 763
   em Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id) na c:'Temp'Release'Working'Newtonsoft.Json'Src'Newtonsoft.Json'Serialization'JsonSerializerInternalReader.cs:linha 1774
   em Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue) na c:'Temp'Release'Working'Newtonsoft.Json'Src'Newtonsoft.Json'Serialization'JsonSerializerInternalReader.cs:linha 384
   em Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue) na c:'Temp'Release'Working'Newtonsoft.Json'Src'Newtonsoft.Json'Serialization'JsonSerializerInternalReader.cs:linha 254
   em Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateList(IList list, JsonReader reader, JsonArrayContract contract, JsonProperty containerProperty, String id) na c:'Temp'Release'Working'Newtonsoft.Json'Src'Newtonsoft.Json'Serialization'JsonSerializerInternalReader.cs:linha 1276
   em Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateList(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue, String id) na c:'Temp'Release'Working'Newtonsoft.Json'Src'Newtonsoft.Json'Serialization'JsonSerializerInternalReader.cs:linha 644
   em Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue) na c:'Temp'Release'Working'Newtonsoft.Json'Src'Newtonsoft.Json'Serialization'JsonSerializerInternalReader.cs:linha 256
   em Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, Object target) na c:'Temp'Release'Working'Newtonsoft.Json'Src'Newtonsoft.Json'Serialization'JsonSerializerInternalReader.cs:linha 763
   em Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id) na c:'Temp'Release'Working'Newtonsoft.Json'Src'Newtonsoft.Json'Serialization'JsonSerializerInternalReader.cs:linha 1774
   em Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue) na c:'Temp'Release'Working'Newtonsoft.Json'Src'Newtonsoft.Json'Serialization'JsonSerializerInternalReader.cs:linha 384
   em Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue) na c:'Temp'Release'Working'Newtonsoft.Json'Src'Newtonsoft.Json'Serialization'JsonSerializerInternalReader.cs:linha 254
   em Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent) na c:'Temp'Release'Working'Newtonsoft.Json'Src'Newtonsoft.Json'Serialization'JsonSerializerInternalReader.cs:linha 177
   em Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType) na c:'Temp'Release'Working'Newtonsoft.Json'Src'Newtonsoft.Json'JsonSerializer.cs:linha 711
   em Newtonsoft.Json.JsonSerializer.Deserialize(JsonReader reader, Type objectType) na c:'Temp'Release'Working'Newtonsoft.Json'Src'Newtonsoft.Json'JsonSerializer.cs:linha 663
   em Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings) na c:'Temp'Release'Working'Newtonsoft.Json'Src'Newtonsoft.Json'JsonConvert.cs:linha 797
   em Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings) na c:'Temp'Release'Working'Newtonsoft.Json'Src'Newtonsoft.Json'JsonConvert.cs:linha 757
   em Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value) na c:'Temp'Release'Working'Newtonsoft.Json'Src'Newtonsoft.Json'JsonConvert.cs:linha 694
   em LoLWebRequests.LoLWeb.WebGETChampion(String realm, Int32 id) na c:'Users'Charon'Documents'Visual Studio 2012'Projects'LoLWebAPI'LoLWebRequests'LoLWeb.cs:linha 23
   em ConsoleTestApp.Program.Main(String[] args) na c:'Users'Charon'Documents'Visual Studio 2012'Projects'LoLWebAPI'ConsoleTestApp'Program.cs:linha 14
   em System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
   em System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
   em Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
   em System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   em System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   em System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   em System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   em System.Threading.ThreadHelper.ThreadStart()
InnerException: 
下面是我用来获取json的代码:
string uri = https://na.api.pvp.net//api/lol/static-data/br/v1.2/champion/1"?locale=en_US&champData=all&api_key=XXX" //key ommited
Uri serviceUri = new Uri(uri);
WebClient downloader = new WebClient();
string jsonWebResult;
try
{
    Stream responseStream = downloader.OpenRead(serviceUri);
    using (StreamReader sr = new StreamReader(responseStream))
    {
        jsonWebResult = sr.ReadToEnd();
    }
}
catch (WebException webEx)
{
    throw webEx;
}
RootObject result = JsonConvert.DeserializeObject<RootObject>(jsonWebResult);

将Json字符串反序列化为复合对象时出错

我只是试着用来自pastebin的字符串和上面使用的类来解析。我成功地将其解析为没有FormatException的结果对象。

我强烈怀疑这是你如何获得jsonString内容的问题。特别是,我怀疑字符串内的双引号可能无法正确转义:

"tooltip" : "Deals {{ e1 }} <span class='"color99FF99'">(+{{ a1 }})</span> magic...",

下面的代码为我工作:

string jsonString =
            "{'"id'":1,'"key'":'"Annie'",'"name'":'"Annie'",'"title'":'"the Dark Child'",'"image'":{'"full'":'"Annie.png'",'"sprite'":'"champion0.png'",'"group'":'"champion'",'"x'":288,'"y'":0,'"w'":48,'"h'":48},'"skins'":[{'"id'":1000,'"name'":'"default'",'"num'":0},{'"id'":1001,'"name'":'"Goth Annie'",'"num'":1},{'"id'":1002,'"name'":'"Red Riding Annie'",'"num'":2},{'"id'":1003,'"name'":'"Annie in Wonderland'",'"num'":3},{'"id'":1004,'"name'":'"Prom Queen Annie'",'"num'":4},{'"id'":1005,'"name'":'"Frostfire Annie'",'"num'":5},{'"id'":1006,'"name'":'"Reverse Annie'",'"num'":6},{'"id'":1007,'"name'":'"FrankenTibbers Annie'",'"num'":7},{'"id'":1008,'"name'":'"Panda Annie'",'"num'":8}],'"lore'":'"In the time shortly before the League, there were those within the sinister city-state of Noxus who did not agree with the evils perpetrated by the Noxian High Command. The High Command had just put down a coup attempt from the self-proclaimed Crown Prince Raschallion, and a crack down on any form of dissent against the new government was underway. These political and social outcasts, known as the Gray Order, sought to leave their neighbors in peace as they pursued dark arcane knowledge. The leaders of this outcast society were a married couple: Gregori Hastur, the Gray Warlock, and his wife Amoline, the Shadow Witch. Together they led an exodus of magicians and other intelligentsia from Noxus, resettling their followers beyond the Great Barrier to the northern reaches of the unforgiving Voodoo Lands. Though survival was a challenge at times, the Gray Order's colony managed to thrive in a land where so many others would have failed.<br><br>Years after the exodus, Gregori and Amoline had a child: Annie. Early on, Annie's parents knew there was something special about their daughter. At the age of two, Annie miraculously ensorcelled a shadow bear - a ferocious denizen of the petrified forests outside the colony - turning it into her pet. To this day she keeps her bear ''Tibbers'' by her side, often keeping him spellbound as a stuffed doll to be carried like a child's toy. The combination of Annie's lineage and the dark magic of her birthplace have given this little girl tremendous arcane power. It is this same girl who now finds herself as one of the most sought-after champions within the League of Legends - even by the city-state that would have exiled her parents had they not fled beforehand.<br><br>''Annie may be one of the most powerful champions ever to have fought in a Field of Justice. I shudder to think of her capabilities when she becomes an adult.''<br>-- High Councilor Kiersta Mandrake'",'"blurb'":'"In the time shortly before the League, there were those within the sinister city-state of Noxus who did not agree with the evils perpetrated by the Noxian High Command. The High Command had just put down a coup attempt from the self-proclaimed Crown ...'",'"allytips'":['"Storing a stun for use with her ultimate can turn the tide of a team fight.'",'"Striking killing blows on minions with Disintegrate enables Annie to farm extremely well early in the game.'",'"Molten Shield is a good spell to cast to work up to Annie's stun, so sometimes it's beneficial to grab at least 1 rank in it early.'"],'"enemytips'":['"Annie's summoned bear, Tibbers, burns opposing units around himself. Try to keep your distance from him after he's been summoned.'",'"Summoner Smite can be used to help take down Tibbers.'",'"Keep an eye out for a white, swirling power around Annie. It means she's ready to unleash her stun.'"],'"tags'":['"Mage'"],'"partype'":'"Mana'",'"info'":{'"attack'":2,'"defense'":3,'"magic'":10,'"difficulty'":4},'"stats'":{'"armor'":12.5,'"armorperlevel'":4,'"attackdamage'":48,'"attackdamageperlevel'":2.625,'"attackrange'":625,'"attackspeedoffset'":0.08,'"attackspeedperlevel'":1.36,'"crit'":0,'"critperlevel'":0,'"hp'":384,'"hpperlevel'":76,'"hpregen'":4.5,'"hpregenperlevel'":0.55,'"movespeed'":335,'"mp'":250,'"mpperlevel'":50,'"mpregen'":6.9,'"mpregenperlevel'":0.6,'"spellblock'":30,'"spellblockperlevel'":0},'"spells'":[{'"name'":'"Disintegrate'",'"description'":'"Annie hurls a mana-infused fireball, dealing damage and refunding the mana cost if it destroys the target.'",'"sanitizedDescription'":'"Annie hurls a mana-infused fireball, dealing damage and refunding the mana cost if it destroys the target.'",'"tooltip'":'"Deals {{ e1 }} <span class='''"color99FF99'''">(+{{ a1 }})</span> magic damage. Mana cost and half the cooldown are refunded if Disintegrate kills the target.'",'"sanitizedTooltip'":'"Deals {{ e1 }} (+{{ a1 }}) magic damage. Mana cost and half the cooldown are refunded if Disintegrate kills the target.'",'"leveltip'":{'"label'":['"Damage'",'"Mana Cost'"],'"effect'":['"{{ e1 }} -> {{ e1NL }}'",'" {{ cost }} -> {{ costnNL }}'"]},'"image'":{'"full'":'"Disintegrate.png'",'"sprite'":'"spell1.png'",'"group'":'"spell'",'"x'":48,'"y'":0,'"w'":48,'"h'":48},'"resource'":'"{{ cost }} Mana'",'"maxrank'":5,'"cost'":[60,65,70,75,80],'"costType'":'"Mana'",'"costBurn'":'"60/65/70/75/80'",'"cooldown'":[4,4,4,4,4],'"cooldownBurn'":'"4'",'"effect'":[[80,115,150,185,220]],'"effectBurn'":['"80/115/150/185/220'"],'"vars'":[{'"key'":'"a1'",'"link'":'"spelldamage'",'"coeff'":[0.8]}],'"range'":[625,625,625,625,625],'"rangeBurn'":'"625'",'"key'":'"Disintegrate'"},{'"name'":'"Incinerate'",'"description'":'"Annie casts a blazing cone of fire, dealing damage to all enemies in the area.'",'"sanitizedDescription'":'"Annie casts a blazing cone of fire, dealing damage to all enemies in the area.'",'"tooltip'":'"Casts a cone of fire dealing {{ e1 }} <span class='''"color99FF99'''">(+{{ a1 }})</span> magic damage to all enemies in the area.'",'"sanitizedTooltip'":'"Casts a cone of fire dealing {{ e1 }} (+{{ a1 }}) magic damage to all enemies in the area.'",'"leveltip'":{'"label'":['"Damage'",'"Mana Cost'"],'"effect'":['"{{ e1 }} -> {{ e1NL }}'",'" {{ cost }} -> {{ costnNL }}'"]},'"image'":{'"full'":'"Incinerate.png'",'"sprite'":'"spell1.png'",'"group'":'"spell'",'"x'":96,'"y'":0,'"w'":48,'"h'":48},'"resource'":'"{{ cost }} Mana'",'"maxrank'":5,'"cost'":[70,80,90,100,110],'"costType'":'"Mana'",'"costBurn'":'"70/80/90/100/110'",'"cooldown'":[8,8,8,8,8],'"cooldownBurn'":'"8'",'"effect'":[[70,115,160,205,250]],'"effectBurn'":['"70/115/160/205/250'"],'"vars'":[{'"key'":'"a1'",'"link'":'"spelldamage'",'"coeff'":[0.85]}],'"range'":[625,625,625,625,625],'"rangeBurn'":'"625'",'"key'":'"Incinerate'"},{'"name'":'"Molten Shield'",'"description'":'"Increases Annie's Armor and Magic Resist and damages enemies who hit Annie with basic attacks.'",'"sanitizedDescription'":'"Increases Annie's Armor and Magic Resist and damages enemies who hit Annie with basic attacks.'",'"tooltip'":'"Increases Armor and Magic Resist by {{ e1 }} for {{ e3 }} seconds. Deals {{ e2 }} <span class='''"color99FF99'''">(+{{ a1 }})</span> magic damage to enemies who attack Annie with basic attacks.'",'"sanitizedTooltip'":'"Increases Armor and Magic Resist by {{ e1 }} for {{ e3 }} seconds. Deals {{ e2 }} (+{{ a1 }}) magic damage to enemies who attack Annie with basic attacks.'",'"leveltip'":{'"label'":['"Damage'",'"Armor Bonus'",'"Magic Resist Bonus'"],'"effect'":['"{{ e2 }} -> {{ e2NL }}'",'"{{ e1 }} -> {{ e1NL }}'",'"{{ e1 }} -> {{ e1NL }}'"]},'"image'":{'"full'":'"MoltenShield.png'",'"sprite'":'"spell1.png'",'"group'":'"spell'",'"x'":144,'"y'":0,'"w'":48,'"h'":48},'"resource'":'"{{ cost }} Mana'",'"maxrank'":5,'"cost'":[20,20,20,20,20],'"costType'":'"Mana'",'"costBurn'":'"20'",'"cooldown'":[0,0,0,0,0],'"cooldownBurn'":'"0'",'"effect'":[[20,30,40,50,60],[20,30,40,50,60],[5,5,5,5,5]],'"effectBurn'":['"20/30/40/50/60'",'"20/30/40/50/60'",'"5'"],'"vars'":[{'"key'":'"a1'",'"link'":'"spelldamage'",'"coeff'":[0.2]}],'"range'":'"self'",'"rangeBurn'":'"self'",'"key'":'"MoltenShield'"},{'"name'":'"Summon: Tibbers'",'"description'":'"Annie wills her bear Tibbers to life, dealing damage to units in the area. Tibbers can attack and also burns enemies that stand near him.'",'"sanitizedDescription'":'"Annie wills her bear Tibbers to life, dealing damage to units in the area. Tibbers can attack and also burns enemies that stand near him.'",'"tooltip'":'"Tibbers appears in a burst of flame dealing {{ e1 }} <span class='''"color99FF99'''">(+{{ a1 }})</span> magic damage to enemies in the target area.<br><br>For the next {{ e6 }} seconds, Tibbers chases down enemies and deals {{ e4 }}<span class='''"color99FF99'''"> (+{{ a2 }})</span> magic damage each second to nearby foes.<br><br><span class='''"color99FF99'''">Tibbers can be controlled by holding the alt key and using the right mouse button or by reactivating this ability.</span>'",'"sanitizedTooltip'":'"Tibbers appears in a burst of flame dealing {{ e1 }} (+{{ a1 }}) magic damage to enemies in the target area. For the next {{ e6 }} seconds, Tibbers chases down enemies and deals {{ e4 }} (+{{ a2 }}) magic damage each second to nearby foes. Tibbers can be controlled by holding the alt key and using the right mouse button or by reactivating this ability.'",'"leveltip'":{'"label'":['"Damage'",'"Tibbers Health'",'"Tibbers Armor and Magic Resist'",'"Tibbers Attack Damage'",'"Cooldown'"],'"effect'":['"{{ e1 }} -> {{ e1NL }}'",'"{{ e2 }} -> {{ e2NL }}'",'"{{ e5 }} -> {{ e5NL }}'",'"{{ e3 }} -> {{ e3NL }}'",'"{{ cooldown }} -> {{ cooldownnNL }}'"]},'"image'":{'"full'":'"InfernalGuardian.png'",'"sprite'":'"spell1.png'",'"group'":'"spell'",'"x'":192,'"y'":0,'"w'":48,'"h'":48},'"resource'":'"{{ cost }} Mana'",'"maxrank'":3,'"cost'":[100,100,100],'"costType'":'"Mana'",'"costBurn'":'"100'",'"cooldown'":[120,100,80],'"cooldownBurn'":'"120/100/80'",'"effect'":[[175,300,425],[1200,2100,3000],[80,105,130],[35,35,35],[30,50,70],[45,45,45]],'"effectBurn'":['"175/300/425'",'"1200/2100/3000'",'"80/105/130'",'"35'",'"30/50/70'",'"45'"],'"vars'":[{'"key'":'"a1'",'"link'":'"spelldamage'",'"coeff'":[0.8]},{'"key'":'"a2'",'"link'":'"spelldamage'",'"coeff'":[0.2]}],'"range'":[600,600,600],'"rangeBurn'":'"600'",'"key'":'"InfernalGuardian'",'"altimages'":[{'"full'":'"InfernalGuardian0.png'",'"sprite'":'"spell12.png'",'"group'":'"spell'",'"x'":144,'"y'":96,'"w'":48,'"h'":48}]}],'"passive'":{'"name'":'"Pyromania'",'"description'":'"After casting 4 spells, Annie's next offensive spell will stun the target for a short duration.'",'"sanitizedDescription'":'"After casting 4 spells, Annie's next offensive spell will stun the target for a short duration.'",'"image'":{'"full'":'"Annie_Passive.png'",'"sprite'":'"passive0.png'",'"group'":'"passive'",'"x'":288,'"y'":0,'"w'":48,'"h'":48}},'"recommended'":[{'"champion'":'"Annie'",'"title'":'"annieDM'",'"type'":'"riot'",'"map'":'"8'",'"mode'":'"ODIN'",'"priority'":false,'"blocks'":[{'"type'":'"starting'",'"items'":[{'"id'":1001,'"count'":1},{'"id'":1063,'"count'":1},{'"id'":2003,'"count'":2}]},{'"type'":'"essential'",'"items'":[{'"id'":3090,'"count'":1},{'"id'":3020,'"count'":1},{'"id'":3029,'"count'":1}]},{'"type'":'"offensive'",'"items'":[{'"id'":3135,'"count'":1},{'"id'":3100,'"count'":1},{'"id'":3165,'"count'":1}]},{'"type'":'"defensive'",'"items'":[{'"id'":3116,'"count'":1},{'"id'":3001,'"count'":1},{'"id'":3174,'"count'":1}]},{'"type'":'"Consumables'",'"items'":[{'"id'":2003,'"count'":1},{'"id'":2004,'"count'":1}]}]},{'"champion'":'"Annie'",'"title'":'"AnnieFB'",'"type'":'"riot'",'"map'":'"12'",'"mode'":'"FIRSTBLOOD'",'"priority'":false,'"blocks'":[{'"type'":'"starting'",'"items'":[{'"id'":1076,'"count'":1},{'"id'":2003,'"count'":2},{'"id'":3342,'"count'":1}]},{'"type'":'"essential'",'"items'":[{'"id'":3020,'"count'":1},{'"id'":3027,'"count'":1},{'"id'":3089,'"count'":1}]},{'"type'":'"offensive'",'"items'":[{'"id'":3128,'"count'":1},{'"id'":3135,'"count'":1},{'"id'":3001,'"count'":1}]},{'"type'":'"defensive'",'"items'":[{'"id'":3116,'"count'":1},{'"id'":3152,'"count'":1},{'"id'":3157,'"count'":1}]},{'"type'":'"Consumables'",'"items'":[{'"id'":2003,'"count'":1},{'"id'":2004,'"count'":1},{'"id'":2044,'"count'":1}]}]},{'"champion'":'"Annie'",'"title'":'"AnnieSR'",'"type'":'"riot'",'"map'":'"1'",'"mode'":'"CLASSIC'",'"priority'":false,'"blocks'":[{'"type'":'"starting'",'"items'":[{'"id'":1056,'"count'":1},{'"id'":2003,'"count'":2},{'"id'":3340,'"count'":1}]},{'"type'":'"essential'",'"items'":[{'"id'":3020,'"count'":1},{'"id'":3027,'"count'":1},{'"id'":3089,'"count'":1}]},{'"type'":'"offensive'",'"items'":[{'"id'":3128,'"count'":1},{'"id'":3135,'"count'":1},{'"id'":3001,'"count'":1}]},{'"type'":'"defensive'",'"items'":[{'"id'":3116,'"count'":1},{'"id'":3152,'"count'":1},{'"id'":3157,'"count'":1}]},{'"type'":'"Consumables'",'"items'":[{'"id'":2003,'"count'":1},{'"id'":2004,'"count'":1},{'"id'":2044,'"count'":1}]}]},{'"champion'":'"Annie'",'"title'":'"AnnieTT'",'"type'":'"riot'",'"map'":'"10'",'"mode'":'"CLASSIC'",'"priority'":false,'"blocks'":[{'"type'":'"starting'",'"items'":[{'"id'":1056,'"count'":1},{'"id'":1001,'"count'":1}]},{'"type'":'"essential'",'"items'":[{'"id'":3020,'"count'":1},{'"id'":3027,'"count'":1},{'"id'":3090,'"count'":1}]},{'"type'":'"offensive'",'"items'":[{'"id'":3135,'"count'":1},{'"id'":3116,'"count'":1},{'"id'":3187,'"count'":1}]},{'"type'":'"defensive'",'"items'":[{'"id'":3152,'"count'":1},{'"id'":3001,'"count'":1},{'"id'":3170,'"count'":1}]},{'"type'":'"Consumables'",'"items'":[{'"id'":2003,'"count'":1},{'"id'":2004,'"count'":1}]}]},{'"champion'":'"Annie'",'"title'":'"Beginner'",'"type'":'"riot-beginner'",'"map'":'"1'",'"mode'":'"CLASSIC'",'"priority'":false,'"blocks'":[{'"type'":'"beginner_Starter'",'"items'":[{'"id'":1056,'"count'":1},{'"id'":2003,'"count'":1}]},{'"type'":'"beginner_Advanced'",'"recMath'":true,'"items'":[{'"id'":1028,'"count'":1},{'"id'":1027,'"count'":1},{'"id'":3010,'"count'":1}]},{'"type'":'"beginner_MovementSpeed'",'"recMath'":true,'"items'":[{'"id'":1001,'"count'":1},{'"id'":3020,'"count'":1}]},{'"type'":'"beginner_LegendaryItem'",'"recMath'":true,'"items'":[{'"id'":3010,'"count'":1},{'"id'":1026,'"count'":1},{'"id'":3027,'"count'":1}]},{'"type'":'"beginner_MoreLegendaryItems'",'"items'":[{'"id'":3151,'"count'":1},{'"id'":3174,'"count'":1},{'"id'":3116,'"count'":1},{'"id'":3089,'"count'":1}]}]},{'"champion'":'"Annie'",'"title'":'"annieHA'",'"type'":'"riot'",'"map'":'"12'",'"mode'":'"ARAM'",'"priority'":false,'"blocks'":[{'"type'":'"starting'",'"items'":[{'"id'":3096,'"count'":1},{'"id'":1001,'"count'":1},{'"id'":2003,'"count'":3},{'"id'":2004,'"count'":3}]},{'"type'":'"essential'",'"items'":[{'"id'":3020,'"count'":1},{'"id'":3089,'"count'":1},{'"id'":3027,'"count'":1}]},{'"type'":'"offensive'",'"items'":[{'"id'":3128,'"count'":1},{'"id'":3001,'"count'":1},{'"id'":3135,'"count'":1}]},{'"type'":'"defensive'",'"items'":[{'"id'":3003,'"count'":1},{'"id'":3157,'"count'":1},{'"id'":3116,'"count'":1}]},{'"type'":'"Consumables'",'"items'":[{'"id'":2003,'"count'":1},{'"id'":2004,'"count'":1}]}]}]}";
MyJsonContext.RootObject result = JsonConvert.DeserializeObject<MyJsonContext.RootObject>(jsonString);

另一方面,您可以用更简单、更友好的方法DownloadString: 替换代码。
try
{
    using (var client = new WebClient())
    {
        jsonResult = client.DownloadString(serviceUri);
    }
}

一旦这些类被我提到的网站自动生成,我注意到将某些字段键入为int和其他字段键入为double(特别是关于Stats类)是不安全的,因为在其他情况下,int现在可能不是int。所以我把它们都改成了double,不是为了解决问题,而是希望,当我最终修复它时,这些类在所有必要的情况下都会很好。

好吧,当我用尽选项时,我又开始查看每个类字段的自动生成类型,我注意到Spell有一个List<int> cooldown字段。我注意到json字符串中的对应值是4.0,五次。我将cooldown的类型更改为List<double>,反序列化工作了。

简而言之,反序列化器永远不会将double强制转换为int,但是自动生成器看到一个带有0的数字作为它的十进制数字,并为它创建一个int字段,从而使自动生成器和反序列化器不兼容。

花了一下午才弄明白。非常感谢所有的帮助,如果没有它,我就会退出,然后做一个丑陋的动态反序列化,然后是一个字段接一个字段的初始化。