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

时间:2014-06-10 18:06:27

标签: c# json json.net json-deserialization

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

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

我无法发布json字符串,因为它有超过34,000个字符。

由于对象使用了大量的合成,我尝试自己生成所需的所有类。当我收到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,我希望我做的一切都正确。顺便说一句,我错误地输入了粘贴的名称。它应该是Annie,而不是anni。它当然,这根本不重要):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);

2 个答案:

答案 0 :(得分:1)

我只是尝试使用来自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);
    }
}

答案 1 :(得分:1)

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

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

简而言之,解串器永远不会将List<double>转换为double,但是自动生成器会看到一个数字为零的十进制数字,它会创建一个int }字段,因此使自动生成器和解串器不兼容。

整整一个下午才发现这一点。非常感谢所有的帮助,没有它,我会退出并进行丑陋的动态反序列化,然后按字段初始化进行字段化。