反射反序列化和自定义属性






3.81/5 (7投票s)
反射反序列化和自定义属性。
引言
上周,我的一个同事想要将一个对象连同自定义属性一起序列化为 JSON。有趣… JSON.NET 默认情况下不允许序列化自定义属性。所以,你必须编写自定义 JSON 转换器来解决这个问题。让我们看看如何解决这个问题。
假设你拥有以下自定义属性类
/// <summary>
/// Complex Type Attribute
/// </summary>
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class ComplexAttribute : System.Attribute
{
public string Type { get; set; }
public string DisplayName { get; set; }
}
此外,你将其用作以下方式
/// <summary>
/// Creating Blog ComplexType
/// </summary>
[JsonConverter(typeof(ComplexTypeConverter))]
public class Blog
{
[ComplexAttribute(Type = "String", DisplayName = "Blog Title")]
public string Title { get; set; }
[ComplexAttribute(Type = "HTML")]
public string Content { get; set; }
}
因此,你期望以下 JSON 序列化输出
{ "Title":{"type":"String","displayname":"Blog Title","value":"Attribute To JSON"}, "Content":{"type":"HTML","displayname":"Content", "value":"<p>This blog is still not implemented</p>"} }
自定义 JsonConverter
JsonConverter
是 JSON.NET 提供的abstract
类,允许你将对象转换为 JSON 格式以及从 JSON 格式转换回来。通过继承它,你可以自定义默认的序列化和反序列化行为,如你所愿。
使用反射读取属性
属性和反射是相辅相成的。因此,当你重写 WriteJson
方法以创建自定义序列化时,你可以使用反射来读取属性值。当反序列化回对象时,我们可以以相同的方式使用反射来设置属性值。
/// <summary>
/// Complex type converter
/// This class will convert attribute as JSON property
/// </summary>
public class ComplexTypeConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (typeof(iComplexType).IsAssignableFrom(objectType));
}
public override object ReadJson
(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
object rootObject = Activator.CreateInstance(objectType);
JToken objJSON = JToken.ReadFrom(reader);
foreach (var token in objJSON)
{
PropertyInfo propInfo = rootObject.GetType().GetProperty
(token.Path, BindingFlags.IgnoreCase | BindingFlags.Public |
BindingFlags.Instance);
if (propInfo.CanWrite)
{
var tk = token as JProperty;
if (tk.Value is JObject)
{
JValue val = tk.Value.SelectToken("value") as JValue;
propInfo.SetValue(rootObject, Convert.ChangeType
(val.Value, propInfo.PropertyType.UnderlyingSystemType), null);
}
else
{
propInfo.SetValue(rootObject, Convert.ChangeType
(tk.Value, propInfo.PropertyType.UnderlyingSystemType), null);
}
}
}
return rootObject;
}
public override void WriteJson
(JsonWriter writer, object value, JsonSerializer serializer)
{
var jo = new JObject();
var type = value.GetType();
foreach (PropertyInfo propInfo in type.GetProperties())
{
if (propInfo.CanRead)
{
object propVal = propInfo.GetValue(value, null);
var cutomAttribute = propInfo.GetCustomAttribute<ComplexAttribute>();
if (cutomAttribute != null)
{
jo.Add(propInfo.Name, JToken.FromObject(new
{ type = cutomAttribute.Type,
displayname = cutomAttribute.DisplayName ?? propInfo.Name,
value = propVal ?? string.Empty }, serializer));
}
else
{
jo.Add(propInfo.Name, JToken.FromObject
(propVal ?? string.Empty, serializer));
}
}
}
jo.WriteTo(writer);
}
}
自己尝试使用 dot net fiddle
分类于: C#, CodeProject, JSON
标签: C#, deserialization, JSON, jsonconvert, reflection, serialization