Json.NET – 控制类对象 – 属性反序列化

我有一个使用JSON.Net反序列化的模型类Link

 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; } } 

头像包含三个属性: DefaultImageUriSmallImageUriMediumImageUri 。 是否可以在Link对象反序列化上创建Avatar对象,该对象将使用: author_avatarauthor_avatar_smallauthor_avatar_medium json fields?

我相信你可以通过编写自己的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(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()); Populate(objectType, jObject, value); var avatar = Activator.CreateInstance(); //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(); if (ignore != null) continue; var custom = p.GetCustomAttribute(); 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(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; } }