Click here to Skip to main content
15,881,600 members
Articles / Programming Languages / C#

Reflection Deserialization and Custom Attributes

Rate me:
Please Sign up or sign in to vote.
3.81/5 (7 votes)
19 Feb 2016CPOL 28K   180   8   2
Reflection deserialization and custom attributes

Introduction

Last week, one of my colleagues wanted to serialize an object along with custom property attribute to JSON. Interesting… JSON.NET, by default, will not allow serializing custom property attribute. So, you have to write custom JSON converter to fix this. Let’s take a look at how you can solve this problem.

Suppose you have following custom attribute class:

C#
/// <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; }

}

Moreover, you use it as below:

C#
/// <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; }
}

So, you are expecting below JSON serializing output:

{
"Title":{"type":"String","displayname":"Blog Title","value":"Attribute To JSON"},
"Content":{"type":"HTML","displayname":"Content",
           "value":"<p>This blog is still not implemented</p>"}
}

Custom JsonConverter

JsonConverter is an abstract class provides with JSON.NET that allows you to convert an object to and from JSON. By inheriting that, you can customize default serialization and deserialization behavior as you want.

Reading Attributes With Reflection

Attributes and reflection go hand in hand. So, when you override WriteJson method to create your custom serialization, you can use the reflection to read the attributes value. When it desterilize back to the object, we can use reflection same way to set the property value.

C#
/// <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);
    }
}

Try yourself with dot net fiddle:

Filed under: C#, CodeProject, JSON
Tagged: C#, deserialization, JSON, jsonconvert, reflection, serialization

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Technical Lead Eyepax IT Consulting (Pvt) Ltd.
Sri Lanka Sri Lanka
Having more than 9 year hands-on industry experience in software development
Responsible for designing, implementing and managing complex software systems with stringent up-time requirement.

Visit my blog

Comments and Discussions

 
QuestioniComplexType - is that really necessary? Pin
danix1310-Feb-17 4:15
danix1310-Feb-17 4:15 
GeneralMy vote of 4 Pin
sjelen19-Feb-16 3:49
professionalsjelen19-Feb-16 3:49 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.