Используя JsonConvert.DeserializeObject для десериализации Json в класс C# POCO
вот мой простой User
класс POCO:
/// <summary>
/// The User class represents a Coderwall User.
/// </summary>
public class User
{
/// <summary>
/// A User's username. eg: "sergiotapia, mrkibbles, matumbo"
/// </summary>
public string Username { get; set; }
/// <summary>
/// A User's name. eg: "Sergio Tapia, John Cosack, Lucy McMillan"
/// </summary>
public string Name { get; set; }
/// <summary>
/// A User's 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's linked accounts.
/// </summary>
public List<Account> Accounts { get; set; }
/// <summary>
/// A collection of the User's awarded badges.
/// </summary>
public List<Badge> Badges { get; set; }
}
и метод, который я использую для десериализации ответа JSON в
7 ответов
вот рабочий пример.
точки:
- декларация
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's username. eg: "sergiotapia, mrkibbles, matumbo"
/// </summary>
[JsonProperty("username")]
public string Username { get; set; }
/// <summary>
/// A User's name. eg: "Sergio Tapia, John Cosack, Lucy McMillan"
/// </summary>
[JsonProperty("name")]
public string Name { get; set; }
/// <summary>
/// A User's 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's linked accounts.
/// </summary>
[JsonProperty("accounts")]
public Account Accounts { get; set; }
/// <summary>
/// A collection of the User's 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;
}
вы можете создать JsonConverter
. См.здесь например, это похоже на ваш вопрос.
другой и более обтекаемый подход к десериализации строки JSON в верблюжьей оболочке в объект POCO в Pascal-оболочке-использовать CamelCasePropertyNamesContractResolver.
Это часть Newtonsoft.формат JSON.Пространство имен сериализации. Этот подход предполагает, что единственное различие между объектом 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;
}
свойство accounts определяется следующим образом:
"accounts":{"github":"sergiotapia"}
ваш POCO заявляет это:
public List<Account> Accounts { get; set; }
попробуйте использовать этот Json:
"accounts":[{"github":"sergiotapia"}]
массив элементов (который будет отображаться в списке) всегда заключен в квадратные скобки.
Edit: учетная запись Poco будет примерно такой:
class Account {
public string github { get; set; }
}
и, возможно, других свойств.
Edit 2: чтобы не использовать массив свойство следующим образом:
public Account Accounts { get; set; }
С чем-то вроде образца класса, который я опубликовал в первом редактировании.
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.`
все сообщение указывает, что можно сериализовать объект списка, но вход должен быть списком JSON. Это означает, что ваш JSON должен содержать
"accounts" : [{<AccountObjectData}, {<AccountObjectData>}...],
где данные AccountObject-это JSON, представляющий объект вашей учетной записи или объект вашего значка
то, что он, кажется, получает в настоящее время
"accounts":{"github":"sergiotapia"}
где accounts-объект JSON (обозначается фигурными скобками), а не массив объектов JSON (массивы обозначаются скобками), чего ты и хочешь. Попробуй!--5-->
"accounts" : [{"github":"sergiotapia"}]
вдоль строк принятого ответа, если у вас есть образец текста JSON, вы можете подключить его к этот конвертер, выберите Параметры и сгенерируйте код c#.
Если вы не знаете тип во время выполнения, эта тема выглядит, как она вписывается.
динамически десериализуйте json в любой переданный объект. в C#
Это не совсем то, что я имел в виду. Что делать, если у вас есть универсальный тип, который будет известен только во время выполнения?
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);
}
}