假设我有一些Json会包含在这样的数据包中:
{
"LinkType1": "google",
"LinkUrl1": "https://plus.google.com/test",
"LinkShow1": 1,
"LinkType2": "facebook",
"LinkUrl2": "https://www.facebook.com/test",
"LinkShow2": 0,
"LinkType3": "linkedin",
"LinkUrl3": "http://www.linkedin.com/test",
"LinkShow3": 1,
"count": 3,
"errorCode": 0,
"errorMessage": "Success"
}
注意一切都是以同一属性的形式返回,但是有一个索引吗?
我希望能够将该数据反序列化,就像它是一个数组而不是单个属性一样。将其反序列化为下面的类的最佳方法是什么?我正在使用Newtonsoft Json库进行序列化,因此使用它的解决方案将是首选。
public class LinksResult
{
public List<LinkData> Links { get; set; }
[JsonProperty("count")]
public int Count { get; set; }
[JsonProperty("errorCode")]
public int ErrorCode { get; set; }
[JsonProperty("errorMessage")]
public string ErrorMessage { get; set; }
}
public class LinkData
{
public string LinkType { get; set; }
public string LinkUrl { get; set; }
public bool LinkShow { get; set; }
}
答案 0 :(得分:1)
您可以使用自定义JsonConverter
将JSON数据反序列化为所需的结构。这是转换器的代码可能是什么样的。
class LinksResultConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(LinksResult));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject obj = JObject.Load(reader);
LinksResult result = new LinksResult();
result.Count = (int)obj["count"];
result.ErrorCode = (int)obj["errorCode"];
result.ErrorMessage = (string)obj["errorMessage"];
result.Links = new List<LinkData>();
for (int i = 1; i <= result.Count; i++)
{
string index = i.ToString();
LinkData link = new LinkData();
link.LinkType = (string)obj["LinkType" + index];
link.LinkUrl = (string)obj["LinkUrl" + index];
link.LinkShow = (int)obj["LinkShow" + index] == 1;
result.Links.Add(link);
}
return result;
}
public override bool CanWrite
{
get { return false; }
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
要使用转换器,只需在[JsonConverter]
类中添加LinksResult
属性,如下所示。 (请注意,使用此方法不需要[JsonProperty]
属性,因为JSON属性名称与实际类成员之间的映射由转换器直接处理。)
[JsonConverter(typeof(LinksResultConverter))]
public class LinksResult
{
public List<LinkData> Links { get; set; }
public int Count { get; set; }
public int ErrorCode { get; set; }
public string ErrorMessage { get; set; }
}
然后,你可以像这样反序列化:
LinksResult result = JsonConvert.DeserializeObject<LinksResult>(json);
答案 1 :(得分:1)
Brian的回答非常好,它让我80%的路到达了我想去的地方。但是,如果在许多不同的对象上发生这种模式,那么反复使用它并不是一个非常好的实现。
我做了一些更通用的东西。一个&#34; Page&#34;会的。
public interface IPage<TItem>
{
int Count { get; set; }
List<TItem> PageItems { get; set; }
}
然后是页面转换器本身。
public class PageConverter<TPage, TItem> : JsonConverter
where TPage : IPage<TItem>, new()
where TItem : new()
{
private readonly Regex _numberPostfixRegex = new Regex(@"\d+$");
public override bool CanWrite
{
get { return false; }
}
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(TPage));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var obj = serializer.Deserialize<JObject>(reader);
var page = new TPage();
serializer.Populate(obj.CreateReader(), page); //Loads everything that isn't a part of the items.
page.PageItems = new List<TItem>();
for (int i = 1; i <= page.Count; i++)
{
string index = i.ToString();
//Find all properties that have a number at the end, then any of those that are the same number as the current index.
//Put those in a new JObject.
var jsonItem = new JObject();
foreach (var prop in obj.Properties().Where(p => _numberPostfixRegex.Match(p.Name).Value == index))
{
jsonItem[_numberPostfixRegex.Replace(prop.Name, "")] = prop.Value;
}
//Deserialize and add to the list.
TItem item = jsonItem.ToObject<TItem>(serializer);
page.PageItems.Add(item);
}
return page;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
那么所有需要的就是在链接结果上实现它:
[JsonConverter(typeof(PageConverter<LinksResult, LinkData>))]
public class LinksResult : IPage<LinkData>
{
public int Count { get; set; }
public List<LinkData> PageItems { get; set; }
}
我发现你可以control the serialization of capitalization with JsonSerializerSettings,所以最好把这个细节留给所选的序列化器,而不是我的转换器。
答案 2 :(得分:0)
以下是您可能适用的类似解决方案。请参阅Serialize json to an object with catch all dictionary property David Hoerster的答案。