Использование JsonConvert.DeserializeObject для десериализации Json в класс С# POCO
Вот мой простой класс User
POCO:
/// <summary>
/// The User class represents a Coderwall User.
/// </summary>
public class User
{
/// <summary>
/// A User username. eg: "sergiotapia, mrkibbles, matumbo"
/// </summary>
public string Username { get; set; }
/// <summary>
/// A User name. eg: "Sergio Tapia, John Cosack, Lucy McMillan"
/// </summary>
public string Name { get; set; }
/// <summary>
/// A User location. eh: "Bolivia, USA, France, Italy"
/// </summary>
public string Location { get; set; }
public int Endorsements { get; set; } //Todo.
public string Team { get; set; } //Todo.
/// <summary>
/// A collection of the User linked accounts.
/// </summary>
public List<Account> Accounts { get; set; }
/// <summary>
/// A collection of the User awarded badges.
/// </summary>
public List<Badge> Badges { get; set; }
}
И метод, который я использую для десериализации ответа JSON в объект User
(этот фактический JSON-вызов здесь):
private User LoadUserFromJson(string response)
{
var outObject = JsonConvert.DeserializeObject<User>(response);
return outObject;
}
Это вызывает исключение:
Невозможно десериализовать текущий объект JSON (например, { "name": "value" }) в тип 'System.Collections.Generic.List`1 [CoderwallDotNet.Api.Models.Account] потому что для этого требуется массив JSON (например, [1,2,3]) для десериализации правильно.
Чтобы исправить эту ошибку, либо измените JSON на массив JSON (например, [1,2,3]) или изменить десериализованный тип, чтобы он был нормальным Тип .NET(например, не примитивный тип типа integer, а не набор тип, подобный массиву или списку), который можно десериализовать из JSON объект. JsonObjectAttribute также можно добавить к типу, чтобы заставить его для десериализации из объекта JSON. Путь "accounts.github", строка 1, позиция 129.
Никогда ранее не работал с этим методом DeserializeObject, я как бы застрял здесь.
Я убедился, что имена свойств в классе POCO совпадают с именами в ответе JSON.
Что я могу попробовать десериализовать JSON в этом классе POCO?
Ответы
Ответ 1
Вот рабочий пример.
Ключевые точки:
- Объявление
Accounts
- Использование атрибута
JsonProperty
.
using (WebClient wc = new WebClient())
{
var json = wc.DownloadString("http://coderwall.com/mdeiters.json");
var user = JsonConvert.DeserializeObject<User>(json);
}
-
public class User
{
/// <summary>
/// A User username. eg: "sergiotapia, mrkibbles, matumbo"
/// </summary>
[JsonProperty("username")]
public string Username { get; set; }
/// <summary>
/// A User name. eg: "Sergio Tapia, John Cosack, Lucy McMillan"
/// </summary>
[JsonProperty("name")]
public string Name { get; set; }
/// <summary>
/// A User location. eh: "Bolivia, USA, France, Italy"
/// </summary>
[JsonProperty("location")]
public string Location { get; set; }
[JsonProperty("endorsements")]
public int Endorsements { get; set; } //Todo.
[JsonProperty("team")]
public string Team { get; set; } //Todo.
/// <summary>
/// A collection of the User linked accounts.
/// </summary>
[JsonProperty("accounts")]
public Account Accounts { get; set; }
/// <summary>
/// A collection of the User awarded badges.
/// </summary>
[JsonProperty("badges")]
public List<Badge> Badges { get; set; }
}
public class Account
{
public string github;
}
public class Badge
{
[JsonProperty("name")]
public string Name;
[JsonProperty("description")]
public string Description;
[JsonProperty("created")]
public string Created;
[JsonProperty("badge")]
public string BadgeUrl;
}
Ответ 2
Вы можете создать JsonConverter
. См. здесь для примера, аналогичного вашему вопросу.
Ответ 3
Другим и более упорядоченным подходом к десериализации строки JSON с верблюжьей оболочкой в объект POCO с паскальным обложением является использование CamelCasePropertyNamesContractResolver.
Это часть пространства имен Newtonsoft.Json.Serialization. Этот подход предполагает, что единственная разница между объектом JSON и POCO заключается в оболочке имен свойств. Если имена свойств пишутся по-разному, вам нужно прибегнуть к использованию атрибутов JsonProperty для отображения имен свойств.
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
. . .
private User LoadUserFromJson(string response)
{
JsonSerializerSettings serSettings = new JsonSerializerSettings();
serSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
User outObject = JsonConvert.DeserializeObject<User>(jsonValue, serSettings);
return outObject;
}
Ответ 4
Свойство учетных записей определяется следующим образом:
"accounts":{"github":"sergiotapia"}
В POCO указано следующее:
public List<Account> Accounts { get; set; }
Попробуйте использовать этот Json:
"accounts":[{"github":"sergiotapia"}]
Массив элементов (который будет отображаться в списке) всегда заключен в квадратные скобки.
Изменить: Учетная запись Poco будет выглядеть примерно так:
class Account {
public string github { get; set; }
}
и, возможно, другие свойства.
Изменить 2: Чтобы не иметь массив, используйте свойство следующим образом:
public Account Accounts { get; set; }
с чем-то вроде класса образца, который я опубликовал в первом редактировании.
Ответ 5
to fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the
deserialized type so that it is a normal .NET type (e.g. not a primitive type like
integer, not a collection type like an array or List) that can be deserialized from a
JSON object.`
Все сообщение указывает, что можно сериализовать объект List, но вход должен быть списком JSON.
Это означает, что ваш JSON должен содержать
"accounts" : [{<AccountObjectData}, {<AccountObjectData>}...],
Где данные AccountObject - это JSON, представляющий объект вашей учетной записи или объект значка
В настоящее время он выглядит как
"accounts":{"github":"sergiotapia"}
Если учетными записями является объект JSON (обозначается фигурной скобкой), а не массив объектов JSON (массивы обозначаются скобками), это то, что вы хотите. Попробуйте
"accounts" : [{"github":"sergiotapia"}]
Ответ 6
Это не совсем то, что я имел в виду. Что вы делаете, если у вас есть общий тип, который будет известен только во время выполнения?
public MyDTO toObject() {
try {
var methodInfo = MethodBase.GetCurrentMethod();
if (methodInfo.DeclaringType != null) {
var fullName = methodInfo.DeclaringType.FullName + "." + this.dtoName;
Type type = Type.GetType(fullName);
if (type != null) {
var obj = JsonConvert.DeserializeObject(payload);
//var obj = JsonConvert.DeserializeObject<type.MemberType.GetType()>(payload); // <--- type ?????
...
}
}
// Example for java.. Convert this to C#
return JSONUtil.fromJSON(payload, Class.forName(dtoName, false, getClass().getClassLoader()));
} catch (Exception ex) {
throw new ReflectInsightException(MethodBase.GetCurrentMethod().Name, ex);
}
}
Ответ 7
В соответствии с принятым ответом, если у вас есть образец текста JSON, вы можете подключить его к этот конвертер, выберите свои параметры и сгенерировать код С#.
Если вы не знаете тип во время выполнения, этот вопрос выглядит так, как будто он подходит.
динамически десериализовать json в любой переданный объект. С#