Отключить классы 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

Ваша проблема двоякая:

  1. У вас нет класса, определенного на корневом уровне. Структура класса должна соответствовать всему JSON, вы не можете просто десериализовать из середины.
  2. Всякий раз, когда у вас есть объект, ключи которого могут измениться, вам нужно использовать 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).