Отключить классы JSON до С#
Ниже представлен (слегка) урезанный ответ, который я получаю от REST API после успешного создания новой записи "код задания". Мне нужно десериализовать ответ на некоторые классы, но я в тупике.
Для справки, я использую JSON.NET в.NET 3.5 (работает в сценарии SSIS в SQL Server 2008 R2), чтобы попытаться выполнить десериализацию. Здесь JSON, которого я, очевидно, не контролирую, поскольку он исходит от другого API:
{
"results":{
"jobcodes":{
"1":{
"_status_code":200,
"_status_message":"Created",
"id":444444444,
"assigned_to_all":false,
"billable":true,
"active":true,
"type":"regular",
"name":"1234 Main Street - Jackson"
},
"2":{
"_status_code":200,
"_status_message":"Created",
"id":1234567890,
"assigned_to_all":false,
"billable":true,
"active":true,
"type":"regular",
"name":"4321 Some Other Street - Jackson"
}
}
}
}
В моем коде С# у меня есть определенный класс JobCode, который только частично отображает значения JSON для свойств - мне не интересны все данные, которые мне вернулись:
[JsonObject]
class JobCode
{
[JsonProperty("_status_code")]
public string StatusCode { get; set; }
[JsonProperty("_status_message")]
public string StatusMessage { get; set; }
[JsonProperty("id")]
public string Id {get; set;}
[JsonProperty("name")]
public string Name { get; set; }
//-------------------------------------------------------------------------------
// Empty constructor for JSON serialization support
//-------------------------------------------------------------------------------
public JobCode() { }
}
Я пытаюсь десериализовать данные с помощью этого вызова:
newResource = JsonConvert.DeserializeObject<JobCode>(jsonResponse);
Где jsonResponse - это код, выведенный выше.
Когда я выполняю код, "newResource" всегда возвращается как null - что не является неожиданным, потому что я знаю, что на самом деле в данных есть несколько кодов задания, и этот код пытается десериализовать его в один объект JobCode. Я попытался создать новый класс под названием "JobCodes", который выглядит так:
class JobCodes
{
[JsonProperty("jobcodes")]
public List<JobCode>_JobCodes { get; set; }
}
И затем я попытался назвать это:
newResource = JsonConvert.DeserializeObject<JobCodes>(jsonResponse);
Но проблема сохраняется - мой объект возврата равен нулю. Мне кажется, что меня выбрасывает присутствие идентификаторов "1" и "2". Я не знаю, как объяснить их присутствие в моем дизайне объектов и/или использовании атрибутов класса/свойства JSON.NET, таких как [JsonObject], [JsonProperty] и т.д.
Когда я запускаю данные JSON через JSON2CSharp, он создает некоторые странные классы, поэтому он не оказался слишком эффективным. Я проверил JSON с несколькими различными валидаторами, и все это проверяется - я просто не знаю, чего я здесь не вижу.
В конечном счете, я хотел бы вернуть список из данных JSON, но я не понимаю, что мне нужно сделать, чтобы это произошло.
Ответы
Ответ 1
Ваша проблема двоякая:
- У вас нет класса, определенного на корневом уровне. Структура класса должна соответствовать всему JSON, вы не можете просто десериализовать из середины.
- Всякий раз, когда у вас есть объект, ключи которого могут измениться, вам нужно использовать
Dictionary<string, T>
. Обычный класс не будет работать для этого; также не будет List<T>
.
Сделайте свои классы следующим:
class RootObject
{
[JsonProperty("results")]
public Results Results { get; set; }
}
class Results
{
[JsonProperty("jobcodes")]
public Dictionary<string, JobCode> JobCodes { get; set; }
}
class JobCode
{
[JsonProperty("_status_code")]
public string StatusCode { get; set; }
[JsonProperty("_status_message")]
public string StatusMessage { get; set; }
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
}
Затем десериализуйте вот так:
RootObject obj = JsonConvert.DeserializeObject<RootObject>(json);
Рабочая демонстрация здесь
Ответ 2
Отличные ответы!
Для тех, кому может понадобиться дополнительная помощь в настройке класса JSON, попробуйте: http://json2csharp.com/#
Отличный способ автоматического создания классов!
Или еще проще, в VS, Goto:
Изменить → Специальная вставка → Вставить как классы JSON
Ответ 3
Поскольку вы не можете изменить схему JSON, и вы не можете установить постоянное количество свойств, я бы предложил вам использовать JObject
var jobject = JObject.Parse(json);
var results = jobject["results"];
var jobcodes = results["jobcodes"];
var output = jobcodes.Children<JProperty>()
.Select(prop => prop.Value.ToObject<JobCode>())
.ToList();
Предупреждение: код предполагает, что JSON всегда в правильной схеме. Вы также должны обрабатывать недопустимую схему (например, если свойство не JobCode
схеме JobCode
).