Хобрук: Ваш путь к мастерству в программировании

JSON.NET анализирует необязательные значения без попытки/поймать

Итак, компания, в которой я работал, попросила меня создать библиотеку C# для компании-клиента, которой нужен доступ к нашему API с помощью .NET. Пока у меня есть рабочая библиотека, но у меня продолжают возникать проблемы с разбором необязательных свойств. Мы используем mongoDB на сервере, и mongoDB не хранит свойства, которые не предоставлены, даже если они определены в схеме.

Например, моя схема может выглядеть так:

{
   name:String,
   id:Number,
   phone:String,
   email:String,
   experience:[]
}

Где, как я делаю документ:

{
   name:"joe",
   id:5,
   phone:"222-222-2222",
}

Свойства email и experience НЕ существуют в моем документе, поэтому мой JSON выглядит точно так, как показано выше. Однако эти значения не являются обязательными, но мне все равно нужно проанализировать остальную часть. Проблема в том, что когда я анализирую приведенный выше код для всех возможных значений, когда я анализирую email или experience, синтаксический анализатор выдает исключение Null Reference Exception, и на то есть веская причина, потому что значение, которое я пытаюсь проанализировать, не существует и способ, которым я ссылка на эти значения выглядит так:

JObject o=JObject.Parse(json); //parse json to JObject json object
string name=(string)o["name"];
int id=(int)o["id"];
string phone=(string)o["phone"];
string email=(string)o["emain"];
List<string> exp=o["experience"].Select(t => (string)t).ToList();

Теперь мой код намного более объективен, я использую LINQ для создания объекта с именем Job и объекта Jobs для хранения JObject таким образом, чтобы вы могли запрашивать из него определенные значения, используя методы объекта Jobs, который инициализируется исходным JSON. нить.

Дело в том, что единственный способ, который я могу придумать для обработки необязательных свойств в JSON, - это попробовать/перехватить каждое значение. Это кажется очень небрежным, и JSON, который мне нужно разобрать, составляет около 40-50 свойств. Кажется, что это будет очень медленно и огромный беспорядок кода. Мне интересно, смогу ли я реализовать это более чистым и эффективным способом.

10.03.2014

  • Вы пробовали var job = JsonConvert.DeserializeObject<Job>(json); ? 11.03.2014
  • Я не уверен, что понимаю. MongoDB не имеет схемы, верно? Вам не нужно ничего разбирать. Вы можете просто сбросить его как документ BSON в Mongo. 11.03.2014
  • @mason это класс Json.Net. 11.03.2014
  • @mason LOL, JObject является частью Json.net 11.03.2014
  • stackoverflow.com/questions/5624934/ 11.03.2014
  • Ах. Я всегда анализировал непосредственно свой собственный класс. Зачем анализировать его в классе JObject вместо пользовательского объекта, которым вы можете управлять? Например, используйте атрибут NullValueAttribute. атрибут? Используйте 1_. 11.03.2014
  • @LewsTherin На бэкэнде мы используем Mongoose с Node.js, поэтому мы определяем схемы. Я думаю, ты меня неправильно истолковываешь. Я не подключаю свой клиент к MongoDB напрямую. Я подключаюсь к API, который предоставляет мне контент из MongoDB в формате JSON через HTTP. 11.03.2014
  • Теперь я в замешательстве. У вас есть Mongoose и MongoDB? Что он? И нет, я не неправильно вас истолковал. 11.03.2014
  • @mason, как я уже сказал, я делаю именно это. Чтобы преобразовать JSON в объект, вы должны сначала определить этот объект, поскольку это невозможно сделать на лету. У меня есть объект с именем Job, это то, что я анализирую в своем JSON. Тем не менее, вы не можете просто разобрать объект, как вы можете это делать с Javascript. Вы должны использовать что-то вроде LINQ, чтобы получить значения и добавить их в свой экземпляр объекта. Особенно, когда JSON, который я извлекаю, содержит встроенные объекты и массивы. Массивы необходимо преобразовать в списки, потому что они не имеют определенной длины в JS. 11.03.2014
  • @LewsTherin, очевидно, вы, Mongoose - это библиотека для подключения к MongoDB с помощью Node.js. 11.03.2014
  • Я не подключаюсь к Mongo с С# напрямую. Я подключаюсь к RESTful API, где JSON обслуживается из базы данных. То, что вы упомянули о LewsTherin, не имеет ничего общего с моими проблемами. Я получаю JSON, который я точно не знаю, имеет ли он определенные значения/свойства, потому что эти свойства не требуются, однако, когда я анализирую эти значения, а их нет, я получаю сообщение об ошибке. Использование try/catch очень грязно, когда вам нужно попробовать/перехватить ~ 50 значений из JSON, где 90% из них встроены в массив, объект или и то, и другое. 11.03.2014
  • Хорошо, я думаю, я запутался, на каком уровне лежит код C #. Ваш клиент подключается к вашему API (предположительно, на C #), который использует Mongoose для подключения к MongoDB с NodeJS... Да, я полностью потерян. 11.03.2014
  • Нет, вы можете перейти непосредственно к заданию, не конвертируя его в JObject. См. Ответ @evanmcdonnal для примера этого. Я смотрю на ваш код, и он никогда не показывает, что вы перешли из JObject в Job. 11.03.2014
  • @tsturzl Кажется, ты что-то упускаешь. перейти к первому_комментарию; 11.03.2014
  • Это потому, что этот код состоит буквально из 200 строк, и я просто хотел его упростить. Я не хотел определять объект Job, поскольку это НЕ ГДЕ МОЯ ПРОБЛЕМА. 11.03.2014
  • @tsturzl Я дал вам ссылку, которая показывает, как это делается. Но вы видели ответ на свой вопрос? Эван? 11.03.2014
  • Если MongoDB или Mongoose не важны для вопроса, не упоминайте их. Просто скажите, что у вас есть JSON, который вы получаете от API. Упоминание MongoDB и Mongoose, кажется, заводит всех в погоню за красной селедкой. 11.03.2014
  • @tsturzl Ваша проблема заключается в том, что вы пытаетесь десериализовать вручную, тогда это то, что Json.NET делает из коробки, как в первом комментарии и ответе Эвана. 11.03.2014
  • @LB Можете ли вы объяснить мне, как именно работает этот метод или где найти информацию о нем? Это кажется относительно недокументированным? 11.03.2014
  • Это самый распространенный способ десериализации. См. документацию Json.NET (она находится в строке 20). 11.03.2014
  • @tsturzl james.newtonking.com/json/help/ index.html?topic=html/ 11.03.2014
  • Я не увидел ответа ниже. Мне просто нужно было обновиться. 11.03.2014

Ответы:


1

Если нет какой-либо веской причины, по которой вы не можете использовать общие методы десериализации/сериализации, я бы рекомендовал изменить ваш подход к их использованию. В общем, я думаю, что тип условного разбора свойств, который вы делаете выше, очень плохая практика. Вот пример;

public class Job
{
   public string name;
   public string id;
   public string phone;
   public string email;
   public string[] experience; // can also be a List<string> without any problems
}

Job j = JsonConvert.DeserializeObject<Job>(jsonString);

string output = JsonConvert.SerializeObject(j);
//will include "optional" parameters, meaning if there is no phone value it will be an empty string but the property name will still be there.

Если вы действительно хотите подтвердить это, скажем, некоторые обязательные параметры включены, но некоторые другие необязательные нет, я бы рекомендовал использовать схемы json в сочетании с json.NET. Вы можете сделать что-то вроде следующего;

//schema in flat text file I read with File.ReadAllText(path);
{
    "type":"object",
    "$schema": "http://json-schema.org/draft-03/schema",
    "required":true,
    "properties":{
        "name": { "type":"string", "required":true },
        "id": { "type":"string", "required":true },
                "phone": { "type":"string", "required":false },
                "email": { "type":"string", "required":false },
                "experience": { "type":"array", "required":true, "items": { "string" } }
    }
}

Затем в коде у вас есть что-то вроде;

JObject obj = JObject.Parse(json);
JsonSchema jscheme = JsonSchema.Parse(File.ReadAllText(thatSchemaAbove));
IList<string> errors;
obj.IsValid(jscheme, out errors);
if (errors.Count() > 0)
{
     //json didn't match the schema, do something about it!
}

EDIT: обработка сложных объектов;

Представьте, что вместо этого ваш json представляет собой объект с массивом из 4_ объектов с именем jobs. Используйте для этого следующие определения классов C#;

public class jobsWrapper
{
    public List<Job> jobs;
}

Любая конструкция, используемая в json, имеет эквивалент C#, вам просто нужно разложить ее и определить, что это такое.

10.03.2014
  • Спасибо, C# определенно не моя сильная сторона. Если бы я захотел установить опыт в список‹строку› вместо массива, было бы это проблемой? 11.03.2014
  • @tsturzl совсем нет. Просто сделайте так в своем классе, и все будет работать точно так же. 11.03.2014
  • Как я могу анализировать встроенные объекты? У меня есть объекты, встроенные в массивы, и объекты внутри других объектов. Этот JSON довольно сложный. 11.03.2014
  • @tsturzl, так что речь идет просто о переводе модели данных в json в классы на C#. Я отредактирую еще один небольшой фрагмент, который может помочь вам двигаться в правильном направлении. Я бы добавил больше деталей, но это очень утомительно, и я не могу копировать/вставлять какую-либо реальную работу по очевидным причинам. 11.03.2014
  • Новые материалы

    Основы принципов S.O.L.I.D, Javascript, Git и NoSQL
    каковы принципы S.O.L.I.D? Принципы SOLID призваны помочь разработчикам создавать надежные, удобные в сопровождении приложения. мы видим пять ключевых принципов. Принципы SOLID были разработаны..

    Как настроить Selenium в проекте Angular
    Угловой | Селен Как настроить Selenium в проекте Angular Держите свое приложение Angular и тесты Selenium в одной рабочей области и запускайте их с помощью Mocha. В этой статье мы..

    Аргументы прогрессивного улучшения почти всегда упускают суть
    В наши дни в кругах веб-разработчиков много болтают о Progressive Enhancement — PE, но на самом деле почти все аргументы с обеих сторон упускают самую фундаментальную причину, по которой PE..

    Введение в Джанго Фреймворк
    Схема «работать умно, а не усердно» В этой и последующих статьях я познакомлю вас с тем, что такое фреймворк Django и как создать свое первое приложение с помощью простых и понятных шагов, а..

    Настольный ПК как «одно кольцо, чтобы править всеми» домашних компьютеров
    Вид после 9 месяцев использования С настольных компьютеров все началось, но в какой-то момент они стали «серверами», и мы все перешли на ноутбуки. В прошлом году я столкнулся с идеей настольных..

    Расширенные методы безопасности для VueJS: реализация аутентификации без пароля
    Руководство, которое поможет вам создавать безопасные приложения в долгосрочной перспективе Безопасность приложений часто упускается из виду в процессе разработки, потому что основная..

    стройный-i18следующий
    Представляем стройную оболочку для i18next. Эта библиотека, основанная на i18next, заключает экземпляр i18next в хранилище svelte и отслеживает события i18next, такие как languageChanged,..