Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Общие вопросы по .NET и C# > JSON.Net Long Deserialization


Автор: uwannadie 15.6.2013, 19:18
есть JSON данные, в которых содержатся строки в формате
Код

"arenaUniqueID ": 123456789000000L 

десериализация производится с помощью JSON.Net
имеется класс под этот JSON
Код

public class UnPickledData
{
    public Dictionary<int, Vehicle> vehicles { get; set; }        
    public long arenaUniqueID { get; set; }
    public Common common { get; set; }
    public Dictionary<int, Player> players { get; set; }
    public Personal personal { get; set; }
}

при попытке десериализации вылетает исключение:
Код

After parsing a value an unexpected character was encountered: L. Path 'arenaUniqueID', line 1, position 51810.

если заменить long на string получается то же самое.

вопрос: как это дело победить?

Автор: Fobos 15.6.2013, 22:13
Вопрос в лоб, а Вы пробовали how to example на сайте проекта? http://james.newtonking.com/projects/json-net.aspx я думаю это было бы хорошей отправной точкой.

Автор: uwannadie 15.6.2013, 22:26
их поиск меня наверное уже ненавидит  smile 

Автор: Fobos 15.6.2013, 22:35
Нет, постойте, чудес не бывает. Если Вы вставляете Вашу строку "arenaUniqueID ": 123456789000000L в их пример она что, тоже падает?

Автор: uwannadie 15.6.2013, 23:15
ну как минимум проблемная строка под их пример не подходит (т.к. там свой класс)

Автор: Fobos 15.6.2013, 23:39
да не подходит, верно подмечено, но по аналогии переделать не получается? Я так понимаю Вы просто что-то напутали. Возьмите их пример и начните медленно переводить к Вашему проекту, на каждой итерации проверяйте работоспособность - проблема сразу найдется.

Автор: uwannadie 16.6.2013, 00:34
да я знаю в чем проблема - парсер не понимает формат, которым описывается long (1234567890L) в с\c++ и пытается его привести к Int64 (сами данные формировались в JSON программой, написанной в связке c++\python)
но вот как побороть эту проблему без использования костылей а-ля найти все вхождения этого и удалить, я не в курсе  smile 

Автор: Экскалупатор 16.6.2013, 11:20
Цитата(uwannadie @  15.6.2013,  18:18 Найти цитируемый пост)
если заменить long на string получается то же самое.

меняется лонг на стринг только в классе или в json строке тоже?

беглое изучение справки на сайте http://james.newtonking.com/projects/json/help/ говорит, что можно попробовать следующее:
1. использовать атрибуты, типа JsonProoertyAttribute или JsonConverterAttribute
2. использовать свой конвертер, т.е. написать наследника от CustomCreationConverter<>, и передавать его вместе с данными которые надо десериализовывать в десериализатор.

примерами они конечно не очень сильно разбрасываются, но если посидеть, то можно вкурить.

Автор: uwannadie 16.6.2013, 14:45
Цитата(Экскалупатор @ 16.6.2013,  11:20)
Цитата(uwannadie @  15.6.2013,  18:18 Найти цитируемый пост)
если заменить long на string получается то же самое.

меняется лонг на стринг только в классе или в json строке тоже?

беглое изучение справки на сайте http://james.newtonking.com/projects/json/help/ говорит, что можно попробовать следующее:
1. использовать атрибуты, типа JsonProoertyAttribute или JsonConverterAttribute
2. использовать свой конвертер, т.е. написать наследника от CustomCreationConverter<>, и передавать его вместе с данными которые надо десериализовывать в десериализатор.

примерами они конечно не очень сильно разбрасываются, но если посидеть, то можно вкурить.

в классе, но толку от этого ноль, т.к. данные все равно в понимании парсера - число ибо без кавычек.
аттрибуты ставил, но результат аналогичный.
сейчас как раз курю над конвертерами

Автор: uwannadie 16.6.2013, 17:23
прикрутил свой конвертер - результат тот же.
причем сам конвертер оперирует нормально и отрабатывает без ошибок, но вот десериализация фейлится ;(
код конвертера (мб все же тут надуплил, хотя там все просто)
Код

using System;
using Newtonsoft.Json;

namespace ReplayManager.Core
{
    class CustomLongConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            return objectType == typeof(long);
        }

        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            return reader.Value.ToString();           
        }

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            throw new NotSupportedException();
        }
    }
}

и сам класс
Код

public class UnPickledData
{
    public Dictionary<int, Vehicle> vehicles { get; set; }
    [JsonConverter(typeof(CustomLongConverter))]
    public string arenaUniqueID { get; set; }
    public Common common { get; set; }
    public Dictionary<int, Player> players { get; set; }
    public Personal personal { get; set; }
}

сам JSON с вырезанными данными (ибо их там 130кб)
Код

{
    'vehicles':{
    ...
    },
    'arenaUniqueID':214197923159382012L,
    'common':{
    ...
    },
    'players':{
    ...
    },
    'personal':{
    ...
    }
}

Автор: Экскалупатор 16.6.2013, 18:52
Цитата(uwannadie @  16.6.2013,  16:23 Найти цитируемый пост)
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            return reader.Value.ToString();           
        }

тут бы наверное надо прочитать собственно значение, и попытаться его распарсить. типа long.Parse() или выяснить можно ли это сделать. поставь тут брекпоинт и посмотри что тут вообще происходит.

Автор: uwannadie 16.6.2013, 19:38
там спокойно извлекается значение, причем вполне нормально.
исключение вызывается сразу после выхода из этой функции.
пробовал втыкать туда try...catch, но функция отрабатывает успешно

п.с. возможно проблема в том, что в JonToken.cs (http://json.codeplex.com/SourceControl/latest#128149) все целочисленные типы фактически рассматриваются как integer?

Автор: Экскалупатор 16.6.2013, 19:57
может быть все что угодно )))

как сейчас выглядит метод? попробуй вернуть лонг(без приведения к object или ToString()).

Автор: uwannadie 16.6.2013, 20:29
Цитата(Экскалупатор @ 16.6.2013,  19:57)
может быть все что угодно )))

как сейчас выглядит метод? попробуй вернуть лонг(без приведения к object или ToString()).

без приведения к object не скомпилится ибо
Код

public abstract object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer);

в http://json.codeplex.com/SourceControl/latest#128133
если конвертер привести к 
Код

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
     return (long)reader.Value;           
}

ну и соответственно поменять в классе, то все равно вываливается ошибка при десериализации

Автор: Экскалупатор 16.6.2013, 22:31
я не очень уверен, но мне почему то кажется что буква L это не совсем вписывается в json формат. json это ж как бы текст, и при парсинге оно очень уделяется внимания этому, и текст без этой буквы уверенно конвертируется в число, но букву эту он почему то всегда считает не числом, а непонятно чем.

Добавлено через 54 секунды
думаю поможет реализация своего парсинга поможет разрулить эту ситуацию...

Автор: uwannadie 16.6.2013, 22:50
Цитата(Экскалупатор @ 16.6.2013,  22:31)
я не очень уверен, но мне почему то кажется что буква L это не совсем вписывается в json формат. json это ж как бы текст, и при парсинге оно очень уделяется внимания этому, и текст без этой буквы уверенно конвертируется в число, но букву эту он почему то всегда считает не числом, а непонятно чем.

Добавлено @ 22:32
думаю поможет реализация своего парсинга поможет разрулить эту ситуацию...

ну для начала попробую спросить у них на форуме, может быть там ответят ЧЯДНТ.

Автор: uwannadie 17.6.2013, 12:38
ответ разработчика впечатлил
http://stackoverflow.com/a/17140207/2350109

Автор: Экскалупатор 17.6.2013, 17:54
ну в принципе я написал тоже самое. это не по формату json. по json это либо строка, либо число. так как формат универсальный то это не допускает привязок к форматам языков.

Автор: uwannadie 17.6.2013, 19:00
Цитата(Экскалупатор @ 17.6.2013,  17:54)
ну в принципе я написал тоже самое. это не по формату json. по json это либо строка, либо число. так как формат универсальный то это не допускает привязок к форматам языков.

ну видимо придется предварительно редактировать JSON перед десериализацией  smile 

Автор: Экскалупатор 17.6.2013, 19:30
Цитата(uwannadie @  17.6.2013,  18:00 Найти цитируемый пост)
ну видимо придется предварительно редактировать JSON перед десериализацией

ну, на мой взгляд, косяк в том коде который формирует такой "json", дай им ссылку на док как должен выглядеть json, может они не в курсе...
но вообще редактировать сырую строку это плохая идея(ИМХО). во-первых, можно очень сильно накосячить. придется все время помнить как и зачем происходит редактирование, ну и надо умудриться не забыть учесть все возможные варианты, а в данном случае это, мягко говоря, не тривиальная задача. особенно учитывая что "1231231L" может быть частью строки вида "bla-bla 123123123L bla-bla" и в этом случае ее надо не изменить, а оставить. А во-вторых, всегда могут появиться еще всякие "нестыковки" и расхождения с форматом. мне кажется тут лучше договориться заранее о формате, дабы потом не огребать за это постоянно. Уже проще что бы сериализация была не в такие числа, а всегда в строку, тут хоть выкрутиться можно будет.

Автор: uwannadie 17.6.2013, 21:19
Цитата(Экскалупатор @ 17.6.2013,  19:30)
Цитата(uwannadie @  17.6.2013,  18:00 Найти цитируемый пост)
ну видимо придется предварительно редактировать JSON перед десериализацией

ну, на мой взгляд, косяк в том коде который формирует такой "json", дай им ссылку на док как должен выглядеть json, может они не в курсе...
но вообще редактировать сырую строку это плохая идея(ИМХО). во-первых, можно очень сильно накосячить. придется все время помнить как и зачем происходит редактирование, ну и надо умудриться не забыть учесть все возможные варианты, а в данном случае это, мягко говоря, не тривиальная задача. особенно учитывая что "1231231L" может быть частью строки вида "bla-bla 123123123L bla-bla" и в этом случае ее надо не изменить, а оставить. А во-вторых, всегда могут появиться еще всякие "нестыковки" и расхождения с форматом. мне кажется тут лучше договориться заранее о формате, дабы потом не огребать за это постоянно. Уже проще что бы сериализация была не в такие числа, а всегда в строку, тут хоть выкрутиться можно будет.

договориться о формате врядл получится, т.к. компания, которая пишет такое - wargaming.net, а я всего лишь пытаюсь вытащить как можно больше инфы из их файлов с реплеями игры

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)