ошибка десериализации строки Json в составной объект

1

Я использую Newtonsoft Json.NET. Их документация не очень помогает.

Мне нужно десериализовать json-строку в объект С# класса моего авторства. Строка json никогда не была объектом этого класса, я получил его с помощью WebRequest.

Я не могу опубликовать строку json, потому что у нее более 34 тысяч символов.

Поскольку объект использует много композиций, я старался генерировать все классы, которые мне нужны. Когда я получил исключение FormatException, строка ввода не была в правильном формате. Я думал, что что-то должно быть не так с моими классами. Затем я нашел этот сайт: http://json2csharp.com/

Он должен генерировать классы, необходимые для вас, поэтому вы можете десериализовать любую строку json. Помимо создания 3 разных классов для одного и того же типа (Image), веб-сайт генерировал те же самые классы, что и у меня, с разными именами здесь и там (для классов, а не для свойств). Это классы:

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 (мой первый раз, используя пастебин, я надеюсь, что все сделал правильно). Кстати, я ошибался в названии пасты. Предполагалось, что это 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);
  • 0
    Покажите нам исключение с деталями исключения
  • 0
    Я думаю, что в этом конкретном случае вам будет очень полезно опубликовать объект Json где-нибудь, например pastebin, и связать его в своем вопросе. Будет трудно дать вам ответ без него.
Показать ещё 4 комментария
Теги:
json-deserialization
json.net

2 ответа

1
Лучший ответ

Как только классы получили автогенерируемый веб-сайт, о котором я упоминал, я заметил, что небезопасно, чтобы определенные поля вводились как int и другие как double (особенно в отношении класса Stats), потому что теперь int не может быть int в каком-то другом случае. Поэтому я изменил их все, чтобы double, а не исправлять проблему, но надеясь, что, когда я, наконец, ее исправлю, классы будут хороши во всех необходимых сценариях.

Ну, когда у меня закончились варианты, я снова начал просматривать автоматически созданные типы для полей каждого класса, и я заметил, что у Spell есть поле List<int> cooldown. Я заметил, что соответствующие значения в строке json были 4,0, пять раз. Я изменил тип cooldown на List<double> и работа десериализации.

Короче говоря, десериализатор никогда не вводит double в int, но автогенератор видит число с нулем в виде десятичной цифры, и он создает для него поле int, что делает автогенератор и десериализатор несовместимыми.

Целый день, чтобы это выяснить. Большое спасибо за всю помощь, без нее я бы ушел и сделал уродливую динамическую десериализацию, а затем полевую инициализацию поля.

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 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 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 toy. The combination of Annie 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 stun, so sometimes it beneficial to grab at least 1 rank in it early.\"],\"enemytips\":[\"Annie summoned bear, Tibbers, burns opposing units around himself. Try to keep your distance from him after he 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 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 Armor and Magic Resist and damages enemies who hit Annie with basic attacks.\",\"sanitizedDescription\":\"Increases Annie 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 next offensive spell will stun the target for a short duration.\",\"sanitizedDescription\":\"After casting 4 spells, Annie 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);
    }
}
  • 0
    Да, нет ошибок с вашей строкой. Проблема в том, что у меня есть двойные кавычки внутри одного из значений JSON. Вы заменили их на две одинарные кавычки. И это сделало работу. Спасибо. Теперь я должен найти способ программно сделать это. Это все, что было не так со строкой?
  • 0
    Да, это по сути все, что не так со строкой. Если вы jsonString код того, как вы создаете / получаете jsonString , это можно посмотреть.
Показать ещё 5 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню