Преобразование сложного JSON в общий список с помощью Newtonsoft

Ниже представлен Json:

[{
    "Result": {
        "description": "Application Security Supp Specialist",
        "code": "40000003"
    }
}, {
    "Result": {
        "description": "Gvt Cyber Intelligence Specialist",
        "code": "40001416"
    }
}, {
    "Result": {
        "description": "Gvt Record Retention Specialist",
        "code": "40001428"
    }
}]

И ниже структура класса, которую я создал, поскольку мне нужно заполнить это в объекте C#. Я пытаюсь создать коллекцию RulesEngineOutput и заполнить ее содержимым json.

public class RulesEngineOutput
{
    [JsonProperty("description")]
    public string Description { get; set; }

    [JsonProperty("code")]
    public string Code { get; set; }
}

public class RulesEngineOutputCollection
{
    public IEnumerable<RulesEngineOutput> ProbableRoles { get; set; }
}

Я пытаюсь добиться этого с помощью кода ниже:

var bodyJson = JsonConvert.SerializeObject(bodyString);
RulesEngineOutputCollection result = new RulesEngineOutputCollection();
foreach (var item in bodyJson)
{
    result = JsonConvert.DeserializeObject<RulesEngineOutputCollection>(item.ToString()); 
}

Но это исключение, так как элемент получает символ, и я думаю, что мне нужно передать объект JSON в цикле, но я не могу его получить. Каждый раз, когда я получаю это строка JSON.

Невозможно десериализовать текущий массив JSON (например, [1,2,3]) в тип 'RulesEngineOutputCollection', так как для этого типа требуется правильно десериализовать объект JSON (например, {\"name\":\"value\"}). \ R \ n Чтобы исправить эту ошибку, либо измените JSON на объект JSON (например, {\"name\":\"value\"}), либо измените десериализованный тип на массив или тип, который реализует интерфейс коллекции (например, ICollection, IList) как List, который можно десериализовать из массива JSON.

3 ответа

Проблема в том, что у вас есть промежуточный объект между вашим RulesEngineOutput и ваша коллекция. Вы должны реструктурировать свои объекты как таковые:

public class RulesEngineOutput
{
    [JsonProperty("description")]
    public string Description { get; set; }

    [JsonProperty("code")]
    public string Code { get; set; }
}

public class RulesEngineOutputResult
{
    public RulesEngineOutput Result { get; set; }
}

public class RulesEngineOutputCollection
{
    public IEnumerable<RulesEngineOutputResult> ProbableRoles { get; set; }
}

И тогда, когда у вас есть эта реструктуризация, вы можете десериализовать прямо к вашему RulesEngineOutputCollection вместо объекта и повторения и десериализации снова.

result = JsonConvert.DeserializeObject<RulesEngineOutputCollection>(bodyString); 

Большое спасибо Макс, Натан и другие. Итак, наконец, я внес некоторые изменения в код, и ниже приведен код, который я изменил, чтобы все заработало:

 var jToken = JObject.Parse(responseContent);
        var bodyString = jToken.SelectToken("body");
        var bodyJson = JsonConvert.SerializeObject(bodyString);


        List<RulesEngineOutput> result = new List<RulesEngineOutput>();


        try
        {

            foreach (var item in bodyString)
            {
                var formattedItem = item.SelectToken("Result");
                var  resultItem = JsonConvert.DeserializeObject<RulesEngineOutput>(formattedItem.ToString());
                   result.Add(resultItem);
            }


        }

Надеюсь, это поможет и другим.

Как сказал Натан Верри, у вас есть объект, наслоенный на другой объект, и из-за этого вы не можете десериализовать данные так, как вы этого хотите. Однако вы можете обойти эту проблему, если сначала создадите массив этих результатов, а затем назначите его вашему ProbableRoles имущество:

var rules = new RulesEngineOutputCollection
{
    ProbableRoles = JsonConvert.DeserializeObject<Result[]>(bodyString).Select(r => r.Data).ToList()
};

public class Result
{
    [JsonProperty("Result")]
    public RulesEngineOutput Data { get; set; }
}

Все остальное остается прежним. Вы в основном создаете новый список из вашего массива результатов. Я также мог бы назначить Select() результат напрямую (без вызова .ToList()), но это гарантирует, что объект действительно имеет данные, а не просто ссылку на перечисление.

Другие вопросы по тегам