我有一个模型类Link
它用 JSON.Net 反序列化。
public class Link
{
[JsonConstructor]
internal Link(int id)
{
Id = id;
}
public int Id { get; internal set; }
[JsonProperty("title")]
public string Title { get; internal set; }
[JsonProperty("description")]
public string Description { get; internal set; }
... and so on
public Avatar AuthorAvatar { get; internal set; }
}
阿凡达包含三个属性:DefaultImageUri
、SmallImageUri
、MediumImageUri
。是否可以在对象反序列化Link
创建 Avatar 对象,该反序列化将使用:author_avatar
、author_avatar_small
、author_avatar_medium
json 字段?
我相信您可以通过编写自己的JsonConverter
来实现这一点 这里有一个例子(我省略了序列化部分,但实现与反序列化非常相似):
样本:
class Program
{
private static void Main(string[] args)
{
var json = @"{
id:1,
title: 'link title',
description: 'link description',
author_avatar:'link',
author_avatar_small:'small link',
author_avatar_medium:'medium link',
}";
var obj = JsonConvert.DeserializeObject<Link>(json);
}
}
类定义:
[JsonConverter(typeof(LinkSerializer))]
public class Link
{
[JsonConstructor]
public Link(int id)
{
Id = id;
}
[JsonIgnore]
public int Id { get; internal set; }
[JsonProperty("title")]
public string Title { get; internal set; }
[JsonProperty("description")]
public string Description { get; internal set; }
public Avatar AuthorAvatar { get; internal set; }
}
public class Avatar
{
[JsonProperty("author_avatar")]
public string DefaultImageUri { get; internal set; }
[JsonProperty("author_avatar_small")]
public string SmallImageUri { get; internal set; }
[JsonProperty("author_avatar_medium")]
public string MediumImageUri { get; internal set; }
}
自定义链接序列化程序:
public class LinkSerializer : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof (Link) == objectType;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var jObject = JObject.Load(reader);
//NOTE:I changed .ctor to publec to simplify the process, we can also check for JsonConstructor attribute on constructors and the call appropriate one
var value = existingValue ?? Activator.CreateInstance(objectType, jObject["id"].Value<int>());
Populate(objectType, jObject, value);
var avatar = Activator.CreateInstance<Avatar>(); //Fill avatar object
Populate(avatar.GetType(),jObject,avatar);
objectType.GetProperty("AuthorAvatar").SetValue(value,avatar); //set avatar object
return value;
}
private static void Populate(Type objectType, JObject jObject, object value)
{
var properties =
objectType.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (var p in properties)
{
var ignore = p.GetCustomAttribute<JsonIgnoreAttribute>();
if (ignore != null)
continue;
var custom = p.GetCustomAttribute<JsonPropertyAttribute>();
var name = custom != null ? custom.PropertyName : p.Name;
var token = jObject[name];
var obj = token != null
? token.ToObject(p.PropertyType)
: p.PropertyType.IsValueType ? Activator.CreateInstance(p.PropertyType) : null;
p.SetValue(value, obj);
}
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
//we just want to deserialize the object so we don't need it here, but the implementation would be very similar to deserialization
}
你的意思是这样吗?
class Program
{
static void Main(string[] args)
{
string json =
@"{
Id: 1,
author_avatar: 'abc',
author_avatar_small: 'small',
author_avatar_medium: 'medium'
}";
var link = JsonConvert.DeserializeObject<Link>(json);
}
}
public class Link
{
public Link(string author_avatar, string author_avatar_small, string author_avatar_medium)
{
AuthorAvatar = new Avatar(author_avatar, author_avatar_small, author_avatar_medium);
}
public int Id { get; set; }
public Avatar AuthorAvatar { get; set; }
}
public class Avatar
{
public Avatar(string author_avatar, string author_avatar_small, string author_avatar_medium)
{
DefaultImageUri = author_avatar;
SmallImageUri = author_avatar_small;
MediumImageUri = author_avatar_medium;
}
public string DefaultImageUri { get; set; }
public string SmallImageUri { get; set; }
public string MediumImageUri { get; set; }
}