Десериализация сложного JSON объекта C#

314
01 ноября 2017, 00:33

Имеется сложный, не стандартный JSON объект:

{
    "id": "62",
    "contact_id": "1",
    "create_datetime": "2017-10-27 01:05:48",
    "update_datetime": null,
    "state_id": "new",
    "total": "332.2800",
    "currency": "RUB",
    "rate": "1.00000000",
    "tax": "0.0000",
    "shipping": "0.0000",
    "discount": "0.0000",
    "assigned_contact_id": null,
    "paid_year": null,
    "paid_quarter": null,
    "paid_month": null,
    "paid_date": null,
    "is_first": "0",
    "unsettled": "0",
    "comment": "",
    "params": {
        "ip": "194.186.172.92",
        "landing": "phimp.gif",
        "sales_channel": "",
        "shipping_address.country": "rus",
        "shipping_address.region": "72",
        "signup_url": "",
        "stock_id": "1",
        "storefront": "",
        "user_agent": "Mozilla\/5.0 (Windows NT 6.1; WOW64) AppleWebKit\/537.36 (KHTML, like Gecko) Chrome\/60.0.3112.113 YaBrowser\/17.9.1.768 Yowser\/2.5 Safari\/537.36"
    },
    "contact": {
        "id": "1",
        "name": "admin",
        "email": "1@1.ru",
        "phone": "79773013881",
        "registered": true,
        "photo_50x50": "Fuserpic50.jpg"
    },
    "items": {
        "84": {
            "id": "84",
            "order_id": "62",
            "name": "",
            "product_id": "171115",
            "sku_id": "218488",
            "sku_code": "516781",
            "type": "product",
            "service_id": null,
            "service_variant_id": null,
            "price": "110.7600",
            "quantity": "3",
            "parent_id": null,
            "stock_id": null,
            "virtualstock_id": null,
            "purchase_price": "0.0000",
            "total_discount": "0.0000",
            "image_id": "83660",
            "image_filename": "",
            "sku_image_id": null,
            "ext": "jpg",
            "file_name": "",
            "file_size": "0"
        }
    }
}

Описал классы:

    public class Order
    {
        public string id { get; set; }
        public string contact_id { get; set; }
        public string create_datetime { get; set; }
        public object update_datetime { get; set; }
        public string state_id { get; set; }
        public string total { get; set; }
        public string currency { get; set; }
        public string rate { get; set; }
        public string tax { get; set; }
        public string shipping { get; set; }
        public string discount { get; set; }
        public object assigned_contact_id { get; set; }
        public object paid_year { get; set; }
        public object paid_quarter { get; set; }
        public object paid_month { get; set; }
        public object paid_date { get; set; }
        public string is_first { get; set; }
        public string unsettled { get; set; }
        public string comment { get; set; }
        public Params _params { get; set; }
        public Contact contact { get; set; }
        public Items items { get; set; }
    }
    public class Params
    {
        public string ip { get; set; }
        public string landing { get; set; }
        public string sales_channel { get; set; }
        public string shipping_addresscountry { get; set; }
        public string shipping_addressregion { get; set; }
        public string signup_url { get; set; }
        public string stock_id { get; set; }
        public string storefront { get; set; }
        public string user_agent { get; set; }
    }
    public class Contact
    {
        public string id { get; set; }
        public string name { get; set; }
        public string email { get; set; }
        public string phone { get; set; }
        public bool registered { get; set; }
        public string photo_50x50 { get; set; }
    }
    public class Items
    {
        public Item[] item { get; set; }
    }
    public class Item
    {
        public string id { get; set; }
        public string order_id { get; set; }
        public string name { get; set; }
        public string product_id { get; set; }
        public string sku_id { get; set; }
        public string sku_code { get; set; }
        public string type { get; set; }
        public object service_id { get; set; }
        public object service_variant_id { get; set; }
        public string price { get; set; }
        public string quantity { get; set; }
        public object parent_id { get; set; }
        public object stock_id { get; set; }
        public object virtualstock_id { get; set; }
        public string purchase_price { get; set; }
        public string total_discount { get; set; }
        public string image_id { get; set; }
        public string image_filename { get; set; }
        public object sku_image_id { get; set; }
        public string ext { get; set; }
        public string file_name { get; set; }
        public string file_size { get; set; }
    }

Провожу десериализацию

var res = JsonConvert.DeserializeObject<Order>(str);

Ошибок не возникает, но возвращается null, т.е. Items = Null.

Грешу на то, что:

"items": {
    "84": {
        "id": "84",
        "order_id": "62",

Здесь что-то не так.

Как победить?

Answer 1

Классы, кстати, можно генерировать на вот этом сайте.

Конкретно здесь ошибка с названием объекта "84". Такого имени класса существовать не может. Возможно, нужно попробовать изменить невалидные имена и попробовать распарсить еще раз. Классы все же рекомендую взять сгенерированные.

Здесь, кстати, тоже имена невалидные

"shipping_address.country": "rus",
"shipping_address.region": "72",

Кстати, вот здесь же не массив:

"items": {
"84": {
    "id": "84",
    "order_id": "62",

Массив выглядит вот так (в квадратных скобочках):

[ "Ford", "BMW", "Fiat" ]
Answer 2

Вы неправильно пытаетесь десериализовать словарь

public class Order
{
    public string id { get; set; }
    public string contact_id { get; set; }
    public string create_datetime { get; set; }
    public object update_datetime { get; set; }
    public string state_id { get; set; }
    public string total { get; set; }
    public string currency { get; set; }
    public string rate { get; set; }
    public string tax { get; set; }
    public string shipping { get; set; }
    public string discount { get; set; }
    public object assigned_contact_id { get; set; }
    public object paid_year { get; set; }
    public object paid_quarter { get; set; }
    public object paid_month { get; set; }
    public object paid_date { get; set; }
    public string is_first { get; set; }
    public string unsettled { get; set; }
    public string comment { get; set; }
    public Params _params { get; set; }
    public Contact contact { get; set; }
    // Словарь
    public Dictionary<int, Item> items { get; set; }
}
Answer 3

Достаточно добавить атрибут к некоторым свойствам сгенерированных Студией классов:

[JsonProperty("84")]
public _84 _84 { get; set; }

А также:

[JsonProperty("params")]
public Params _params { get; set; }

PS: конечно, желательно переименовать все свойства в соответствии с PascalCase, снабдив их атрибутом JsonProperty для маппинга:

[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("contact_id")]
public string ContactId { get; set; }

И т. д.

Answer 4

Все получилось. так работает:

public Dictionary<int, Item> items { get; set; }
READ ALSO
Selenium | NoSuchWindowException

Selenium | NoSuchWindowException

Как можно обойти исключение NoSuchWindowException в Selenium ?

302
Изменение объектов GUI через SynchronizationContext

Изменение объектов GUI через SynchronizationContext

Почему возможно изменить объекты формы (свойства объектов: buttonCaption = "") только через SynchronizationContext (т

257
Дописать текст в конец файла

Дописать текст в конец файла

Как дописать данные построчно из 1txt в конец 2

379
C# Чтение и запись потока в одном классе

C# Чтение и запись потока в одном классе

Есть ли вnet класс, который может делать и чтении и запись данных в файл?

253