Десериализация данных JSON в C # с использованием JSON.NET - PullRequest
140 голосов
/ 30 марта 2010

Я относительно новичок в работе с данными C # и JSON и ищу руководства. Я использую C # 3.0, с .NET3.5SP1 и JSON.NET 3.5r6.

У меня есть определенный класс C #, который мне нужно заполнить из структуры JSON. Однако не каждая структура JSON для записи, получаемой из веб-службы, содержит все возможные атрибуты, определенные в классе C #.

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

JsonSerializer serializer = new JsonSerializer();
var o = (JObject)serializer.Deserialize(myjsondata);

MyAccount.EmployeeID = (string)o["employeeid"][0];

Каков наилучший способ десериализации структуры JSON в класс C # и обработки возможных пропущенных данных из источника JSON?

Мой класс определен как:

  public class MyAccount
  {

    [JsonProperty(PropertyName = "username")]
    public string UserID { get; set; }

    [JsonProperty(PropertyName = "givenname")]
    public string GivenName { get; set; }

    [JsonProperty(PropertyName = "sn")]
    public string Surname { get; set; }

    [JsonProperty(PropertyName = "passwordexpired")]
    public DateTime PasswordExpire { get; set; }

    [JsonProperty(PropertyName = "primaryaffiliation")]
    public string PrimaryAffiliation { get; set; }

    [JsonProperty(PropertyName = "affiliation")]
    public string[] Affiliation { get; set; }

    [JsonProperty(PropertyName = "affiliationstatus")]
    public string AffiliationStatus { get; set; }

    [JsonProperty(PropertyName = "affiliationmodifytimestamp")]
    public DateTime AffiliationLastModified { get; set; }

    [JsonProperty(PropertyName = "employeeid")]
    public string EmployeeID { get; set; }

    [JsonProperty(PropertyName = "accountstatus")]
    public string AccountStatus { get; set; }

    [JsonProperty(PropertyName = "accountstatusexpiration")]
    public DateTime AccountStatusExpiration { get; set; }

    [JsonProperty(PropertyName = "accountstatusexpmaxdate")]
    public DateTime AccountStatusExpirationMaxDate { get; set; }

    [JsonProperty(PropertyName = "accountstatusmodifytimestamp")]
    public DateTime AccountStatusModified { get; set; }

    [JsonProperty(PropertyName = "accountstatusexpnotice")]
    public string AccountStatusExpNotice { get; set; }

    [JsonProperty(PropertyName = "accountstatusmodifiedby")]
    public Dictionary<DateTime, string> AccountStatusModifiedBy { get; set; }

    [JsonProperty(PropertyName = "entrycreatedate")]
    public DateTime EntryCreatedate { get; set; }

    [JsonProperty(PropertyName = "entrydeactivationdate")]
    public DateTime EntryDeactivationDate { get; set; }

  }

А пример JSON для разбора:

{
    "givenname": [
        "Robert"
    ],
    "passwordexpired": "20091031041550Z",
    "accountstatus": [
        "active"
    ],
    "accountstatusexpiration": [
        "20100612000000Z"
    ],
    "accountstatusexpmaxdate": [
        "20110410000000Z"
    ],
    "accountstatusmodifiedby": {
        "20100214173242Z": "tdecker",
        "20100304003242Z": "jsmith",
        "20100324103242Z": "jsmith",
        "20100325000005Z": "rjones",
        "20100326210634Z": "jsmith",
        "20100326211130Z": "jsmith"
    },
    "accountstatusmodifytimestamp": [
        "20100312001213Z"
    ],
    "affiliation": [
        "Employee",
        "Contractor",
        "Staff"
    ],
    "affiliationmodifytimestamp": [
        "20100312001213Z"
    ],
    "affiliationstatus": [
        "detached"
    ],
    "entrycreatedate": [
        "20000922072747Z"
    ],
    "username": [
        "rjohnson"
    ],
    "primaryaffiliation": [
        "Staff"
    ],
    "employeeid": [
        "999777666"
    ],
    "sn": [
        "Johnson"
    ]
}

Ответы [ 8 ]

272 голосов
/ 27 января 2012

Использование

var rootObject =  JsonConvert.DeserializeObject<RootObject>(string json);

Создайте свои классы на JSON 2 C #


Документация Json.NET: Сериализация и десериализация JSON с Json.NET

77 голосов
/ 30 марта 2010

Вы пытались использовать универсальный метод DeserializeObject?

JsonConvert.DeserializeObject<MyAccount>(myjsondata);

Любые пропущенные поля в данных JSON следует просто оставить пустыми.

UPDATE:

Если строка JSON является массивом, попробуйте следующее:

var jarray = JsonConvert.DeserializeObject<List<MyAccount>>(myjsondata);

jarray должен быть List<MyAccount>.

ДРУГОЕ ОБНОВЛЕНИЕ:

Исключение, которое вы получаете, не согласуется с массивом объектов - я думаю, что у сериализатора возникли проблемы с вашим типом accountstatusmodifiedby, заданным в словаре.

Попробуйте исключить свойство accountstatusmodifiedby из сериализации и посмотрите, поможет ли это. Если это так, возможно, вам придется представлять это свойство по-другому.

Документация: Сериализация и десериализация JSON с Json.NET

49 голосов
/ 17 ноября 2013

Ответ воспроизведен с https://stackoverflow.com/a/10718128/776476

Вы можете использовать тип C # dynamic, чтобы упростить задачу. Этот метод также упрощает ре-факторинг, поскольку он не зависит от волшебных строк.

Json

Строка json ниже представляет собой простой ответ на вызов HTTP API и определяет два свойства: Id и Name.

{"Id": 1, "Name": "biofractal"}

C #

Используйте JsonConvert.DeserializeObject<dynamic>(), чтобы десериализовать эту строку в динамический тип, а затем просто получить доступ к ее свойствам обычным способом.

var results = JsonConvert.DeserializeObject<dynamic>(json);
var id = results.Id;
var name= results.Name;

Примечание : ссылка NuGet для сборки NewtonSoft: http://nuget.org/packages/newtonsoft.json. Не забудьте добавить: using Newtonsoft.Json; для доступа к этим классам.

8 голосов
/ 22 декабря 2011

Вы можете использовать:

JsonConvert.PopulateObject(json, obj);

здесь: json - строка json, obj - целевой объект. См .: Пример

Примечание: PopulateObject() не удалит данные списка obj, после того как Populate(), obj's член списка будет содержать свои исходные данные и данные из строки json

3 голосов
/ 31 июля 2014

Опираясь на ответ bbant, это мое полное решение для десериализации JSON с удаленного URL.

using Newtonsoft.Json;
using System.Net.Http;

namespace Base
{
    public class ApiConsumer<T>
    {
        public T data;
        private string url;

        public CalendarApiConsumer(string url)
        {
            this.url = url;
            this.data = getItems();
        }

        private T getItems()
        {
            T result = default(T);
            HttpClient client = new HttpClient();

            // This allows for debugging possible JSON issues
            var settings = new JsonSerializerSettings
            {
                Error = (sender, args) =>
                {
                    if (System.Diagnostics.Debugger.IsAttached)
                    {
                        System.Diagnostics.Debugger.Break();
                    }
                }
            };

            using (HttpResponseMessage response = client.GetAsync(this.url).Result)
            {
                if (response.IsSuccessStatusCode)
                {
                    result = JsonConvert.DeserializeObject<T>(response.Content.ReadAsStringAsync().Result, settings);
                }
            }
            return result;
        }
    }
}

Использование будет выглядеть так:

ApiConsumer<FeedResult> feed = new ApiConsumer<FeedResult>("http://example.info/feeds/feeds.aspx?alt=json-in-script");

Где FeedResult - класс, сгенерированный с помощью Xamasoft JSON Class Generator

Вот снимок экрана с настройками, которые я использовал, с учетом странных имен свойств, которые веб-версия *1013* не могла объяснить.

Xamasoft JSON Class Generator

1 голос
/ 20 августа 2015

Я нашел свой, я построил мой объект неправильно. Я использовал http://json2csharp.com/, чтобы сгенерировать свой класс объектов из JSON. Когда у меня был правильный Oject, я мог читать без проблем. Норбит, ошибка Нуба. Думаю, я бы добавил его на тот же случай.

1 голос
/ 04 сентября 2012

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

Следующий код был создан с учетом динамического метода.

dynObj = (JArray)JsonConvert.DeserializeObject(nvm);

        foreach (JObject item in dynObj)
        {
            foreach (JObject trend in item["trends"])
            {
         Console.WriteLine("{0}-{1}-{2}", trend["query"], trend["name"], trend["url"]);

            }
        }

Этот код в основном позволяет получить доступ к членам, содержащимся в строке Json. Просто по-другому, без необходимости занятий. query, trend и url - объекты, содержащиеся в строке Json.

Вы также можете использовать этот сайт . Не доверяйте классам на 100%, но вы поняли.

0 голосов
/ 12 апреля 2012

Предполагая, что ваши примеры данных верны, ваше имя и другие записи, заключенные в квадратные скобки, являются массивами в JS ... вы захотите использовать List для этих типов данных. и список, скажем, accounttstatusexpmaxdate ... Я думаю, что в вашем примере даты неправильно отформатированы, хотя и неуверенно относительно того, что еще неверно в вашем примере.

Это старый пост, но я хотел отметить проблемы.

...