Andrey on .NET | Быстрое создание C# классов на базе json или xml

Быстрое создание C# классов на базе json или xml

При работе с веб-сервисами, периодически возникает задача создавать классы для десериализации данных, полученных в формате json или xml. Зачастую, ввиду большого числа полей и глубины вложенности данных, это достаточно утомительное занятие. Упростить и ускорить его поможет Visual Studio 2013.

В первую очередь потребуются сами данные в формате json/xml. Получить их можно разными способами:

  • сделать запрос к серверу из браузера, в некоторых случаях этого будет достаточно;
  • воспользоваться плагинами для браузера, предоставляющими такие дополнительные возможности, как отправку POST, авторизацию и т.д. (например Postman для Chrome);
  • написать код получения ответа в создаваемом приложении (ведь он все равно потребуется). Поставить точку останова и в отладке скопировать данные из переменной, содержащей ответ в виде текста.
  • воспользоваться сервисами генерации json по шаблону (например: json-generator.com)

Полученный ответ необходимо скопировать в буфер обмена.

Теперь создадим пустой C# файл. В нем не должно быть ничего, кроме указания namespace. Курсор поставим внутрь namespace, куда будет вставлен код созданных классов.

namespace MyProject.Namespace
{

}

Последний шаг – запускаем генерацию. Для этого в меню Visual Studio выбираем EDIT > Paste Special > Paste JSON as Classes.

В результате будут созданы необходимые C# классы. Например:

namespace MyProject.Namespace
{
    public class Rootobject
    {
        public Class1[] Property1 { get; set; }
    }

    public class Class1
    {
        public int id{ get; set; }
        public Name name { get; set; }
        public Friend[] friends { get; set; }
    }

    public class Name
    {
        public string first { get; set; }
        public string last { get; set; }
    }

    public class Friend
    {
        public int id { get; set; }
        public string name { get; set; }
    }
}

Корневой класс будет называться Rootobject. Имена остальных, где это возможно будут выведены из названий полей.

Можно провести небольшой рефакторинг, например дав Rootobject и Class1 более осмысленные названия и разместив каждый класс в отдельном файле. Но даже без этого полученный код уже можно использовать для десериализации json.

Rootobject data = JsonConvert.DeserializeObject<Rootobject>(textResponse);

Комментарии (13) -

Elman Aliev 13.11.2014 20:46:20

Полезный инструмент. Спасибо.
Андрей, у Вас опечатка в предложении:
"Для этого в меню Viusal Studio выбираем EDIT > Paste Special > Paste JSON as Classes." -> VisualStudio.

Спасибо, что поделили опытом, Андрей).

Хотел задать вопрос не по теме, если можно.

Вот я читаю данные по url, который возвращает xml. Теперь мне надо эти данные сохранить в базу данных. То есть база данных у меня заполняется только вот таким образом. Я десериализовал xml и получил набор связанных классов. Потом я воспользовался парадигмой entity framework code first. То есть создал контекст и привязал к нему корневой десериализованный класс (подключил к нему свои классы таким образом). Потом просто вызвал SaveChanges() и база со всеми таблицами и данными создалась и заполнилась. Вопрос в том, правильно ли я делаю? И как в таком случае поступили бы вы? И вообще какая тут есть хорошая практика, когда из xml/json нужно данные все прочитать и сохранить в базу через entity framework.
Еще я думал над тем, что можно не десериализовывать xml, а через ADO.NET dataset раскидать данные по таблицам, а потом уже сделать модель entity framework из базы и на более высоких уровнях работать с этой моделью.

Спасибо

stopkadr В принципе подход нормальный. Единственное, на что бы я еще посмотрел, это насколько удобна для дальнейшей работы и, особенно, хранения полученная структура. В этом случае модели BL и модели в DAL могут отличаться от классов, полученных из XML Но это уже специфика, для решения которой надо вникать в суть самой логики и задачи.

Кроме того, особенно если данных много, то можно даже пойти от обратного. Т.е. создать оптимальную модель БД (как проект, включая специфические типы данных, индексы итд), связать ее с классами CodeFirst и сделать уже работу с хранилищем через полученный слой.

Бумбараш 12.01.2016 15:50:14

Привет, можешь подсказать, как распилить сие? Ранее не было опыта работы с JSON, а все пример, что нахожу для опытных. Требуется парсить и складывать в таблицу. Данный код планирую запихать в SSIS пакет в перспективе.

{
  "response": {
    "count": 10,
    "items": [{
      "message": {
        "id": 48,
        "date": 1451410872,
        "out": 1,
        "user_id": 15869,
        "read_state": 1,
        "title": " ... ",
        "body": "Одмином сделал вас)"
      },
      "in_read": 47,
      "out_read": 48
    }, {
      "message": {
        "id": 45,
        "date": 1451408228,
        "out": 1,
        "user_id": 494075,
        "read_state": 1,
        "title": " ... ",
        "body": "321"
      },
      "in_read": 44,
      "out_read": 45
    }, {
      "message": {
        "id": 26,
        "date": 1451044032,
        "out": 0,
        "user_id": 3332747,
        "read_state": 1,
        "title": " ... ",
        "body": "",
        "attachments": [{
          "type": "sticker",
          "sticker": {
            "id": 2467,
            "product_id": 75,
            "photo_64": "http:\/\/vk.com\/images\/stickers\/2467\/64b.png",
            "photo_128": "http:\/\/vk.com\/images\/stickers\/2467\/128b.png",
            "photo_256": "http:\/\/vk.com\/images\/stickers\/2467\/256b.png",
            "photo_352": "http:\/\/vk.com\/images\/stickers\/2467\/352b.png",
            "photo_512": "http:\/\/vk.com\/images\/stickers\/2467\/512b.png",
            "width": 220,
            "height": 256
          }
        }]
      },
      "in_read": 26,
      "out_read": 25
    }]
  }
}

А в чем проблема? Классы прекрасно выделяются методом описанным выше. Остается только получить строку из источника, сконвертировать в объект через  JsonConvert.DeserializeObject и сохранить в БД.

Бумбараш 12.01.2016 17:38:14

Описал данные в классе, Rootobject data = JsonConvert.DeserializeObject<Rootobject>(s); Прош��а без ругани. Теперь остается проблем с доступом к конкретным полям, для последующей выгрузки в таблицу. Ну и, разумеется, как это перевести в итерации и грузить построчно? Если я правильно понимаю, то после парсинга объект "цельный".

У data будет массив объектов типа соответствующего response. Перебираем его с for/foreach или используем LINQ для поиска в массиве. Ну и дальше уже по свойствам вложенных объектов в зависимости от задачи.

Загрузка построчно это в смысле кусками? Объект сильно большой? Можно брать по одной записи response и десериализовывать уже его.

Если нет доступа к VS или в Вашей VS нет меню конвертации, можно воспользоваться онлайн сервисами, для получения C# классов. Их сотни, например https://www.usetoolz.ru
А вообще можно и без классов обойтись - рефлексией, но это геморнее...

Роман 15.12.2017 19:21:47

Все сделал по инструкциям, получил json ответ,:
{"error":{"error_code":5,"error_msg":"User authorization failed: invalid access_token (4).","request_params":[{"key":"oauth","value":"1"},{"key":"method","value":"METHOD_NAME"},{"key":"PARAMETERS","value":""},{"key":"v","value":"V"}]}}

создал классы
public class Rootobject
        {
            public Error error { get; set; }
        }

        public class Error
        {
            public int error_code { get; set; }
            public string error_msg { get; set; }
            public Request_Params[] request_params { get; set; }
        }

        public class Request_Params
        {
            public string key { get; set; }
            public string value { get; set; }
        }
Вызвал в нужном месте:

Rootobject clas = new Rootobject();
            clas = JsonConvert.DeserializeObject<Rootobject>(e.Url.ToString());

исключение типа
+    $exception  {"Unexpected character encountered while parsing value: h. Path '', line 0, position 0."}  Newtonsoft.Json.JsonReaderException

Не пойму что он в 0 позиции и строке неможет распарсить что то?

Роман 15.12.2017 19:29:56

Все исправил, работает. Оказывается не от туда response брал.

Роман 15.12.2017 19:37:44

И еще можно вопрос,
Есть класс Rootobject:
//////////////////////////////////////
namespace programm
{
        public class Rootobject
        {
            public Error error { get; set; }
        }
        public class Error
        {
            public int error_code { get; set; }
            public string error_msg { get; set; }
            public Request_Params[] request_params { get; set; }
        }
        public class Request_Params
        {
            public string key { get; set; }
            public string value { get; set; }
        }
}

Обращаюсь с другого места программы к классу Rootobject
и VS видит только класс error, остальных не видит, что я не правильно сделал?
Скриншот прикладываю http://prntscr.com/hnym7w

Роман Ну так судя по скрину все верно. Остальные же классы у вас внутри Error.

Денис 04.07.2019 16:18:10

Спасибо за статью. Столько времени зря потрачено...(
У себя еще назначил клавиши для удобства Ctrl+C, Ctrl+J => теперь создание моделей почти мгновенно происходит.

Добавить комментарий