Я относительно новичок в работе с данными С# и JSON, и я ищу руководство. Я использую С# 3.0, с .NET3.5SP1 и JSON.NET 3.5r6.
У меня есть определенный класс С#, который мне нужно заполнить из структуры JSON. Однако не каждая структура JSON для записи, полученной из веб-службы, содержит все возможные атрибуты, которые определены в классе С#.
Я делаю то, что кажется неправильным, трудным и просто выбирает каждое значение по одному из JObject и преобразует строку в требуемое свойство класса.
JsonSerializer serializer = new JsonSerializer();
var o = (JObject)serializer.Deserialize(myjsondata);
MyAccount.EmployeeID = (string)o["employeeid"][0];
Каков наилучший способ десериализации структуры JSON в класс С# и обработка возможных отсутствующих данных из источника 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"
]
}
Ответ 1
использование
var rootObject = JsonConvert.DeserializeObject<RootObject>(string json);
Создайте свои классы на JSON 2 С#
Документация по Json.NET: Сериализация и десериализация JSON с помощью Json.NET
Ответ 2
Пробовали ли вы использовать общий метод DeserializeObject?
JsonConvert.DeserializeObject<MyAccount>(myjsondata);
Любые отсутствующие поля в данных JSON должны просто оставить NULL.
UPDATE:
Если строка JSON является массивом, попробуйте следующее:
var jarray = JsonConvert.DeserializeObject<List<MyAccount>>(myjsondata);
jarray
должен быть List<MyAccount>
.
ДРУГОЕ ОБНОВЛЕНИЕ:
Исключением, которое вы получаете, не согласуется с массивом объектов - я думаю, что у сериализатора возникают проблемы с вашим свойством accountstatusmodifiedby
с типом словаря.
Попробуйте исключить свойство accountstatusmodifiedby
из сериализации и посмотрите, помогает ли это. Если это так, вам может потребоваться представить это свойство по-разному.
Документация: Сериализация и десериализация JSON с Json.NET
Ответ 3
Ответ воспроизведен из fooobar.com/questions/27521/...
Вы можете использовать тип С# dynamic
, чтобы упростить задачу. Этот метод также упрощает повторный факторинг, поскольку он не полагается на магические строки.
Json
Строка json
ниже - это простой ответ от HTTP-вызова api и определяет два свойства: Id
и Name
.
{"Id": 1, "Name": "biofractal"}
С#
Используйте 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;
для доступа к этим классам.
Ответ 4
Вы можете использовать:
JsonConvert.PopulateObject(json, obj);
здесь: json
- строка json, obj
- целевой объект. См.: пример
Примечание: PopulateObject()
не будет удалять данные списка obj, после того, как элемент Populate()
, obj's
будет содержать свои исходные данные и данные из строки json
Ответ 5
Построение ответа 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
Вот скриншот настроек, которые я использовал, с учетом странных имен свойств, которые веб-версия не могла учитываться.
![Xamasoft JSON Class Generator]()
Ответ 6
Вы можете попробовать проверить некоторые генераторы классов в Интернете для получения дополнительной информации. Тем не менее, я считаю, что некоторые из ответов были полезны. Здесь мой подход, который может быть полезен.
Следующий код был сделан с учетом динамического метода.
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%, но вы получаете идею.
Ответ 7
Я обнаружил, что создал свой объект неправильно. Я использовал http://json2csharp.com/, чтобы сгенерировать мне свой класс объектов из JSON. Как только у меня был правильный Oject, я смог бросить без проблем. Норбит, ошибка Нооба. Думаю, я добавлю его, если у вас будет такая же проблема.
Ответ 8
Предполагая, что ваши данные образца верны, ваше имя и другие записи, заключенные в скобки, являются массивами в JS... вы хотите использовать List для этих типов данных. и List для say accountstatusexpmaxdate... Я думаю, что вы, например, неверно отформатировали даты, поэтому не знаете, что еще неверно в вашем примере.
Это старый пост, но хотелось бы обратить внимание на проблемы.