Преобразование сложного 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()
), но это гарантирует, что объект действительно имеет данные, а не просто ссылку на перечисление.