Object转化成JSON字符串

有关JSON的介绍,请参见http://www.json.org/json-zh.html
对于一个类,其中可能包括field, property,方法不做JSON序列化。我们可以去field和property进行JSON转化。
模仿反射中的FieldInfo和PropertyInfo, 两者都继承于MemberInfo,我们定义三个类,用来存储field,property的信息:

JsonMemberInfo.cs

using System;



namespace XXX.JsonSerializer

{

    public class JsonMemberInfo

    {

        protected JsonAttrribute attribute;



        public JsonAttrribute Attribute

        {

            get

            {

                return this.attribute;

            }

            set

            {

                this.attribute = value;

            }

        }

    }

}
 
JsonFieldInfo.cs
 
using System;

using System.Collections.Generic;

using System.Text;

using System.Reflection;



namespace XXX.JsonSerializer

{

    public class JsonFieldInfo : JsonMemberInfo

    {

        private FieldInfo info;



        public FieldInfo Info

        {

            get

            {

                return this.info;

            }

            set

            {

                this.info = value;

            }

        }



        public string JsonName

        {

            get

            {

                if ((this.attribute != null) && (this.attribute.JsonName != string.Empty))

                {

                    return this.attribute.JsonName;

                }

                else

                {

                    return this.info.Name;

                }

            }

        }



        public JsonFieldInfo(FieldInfo i)

        {

            this.info = i;

        }

    }

}

 

JsonPropertyInfo.cs

using System;

using System.Collections.Generic;

using System.Text;

using System.Reflection;



namespace XXX.JsonSerializer

{

    public class JsonPropertyInfo : JsonMemberInfo

    {

        private PropertyInfo info;



        public PropertyInfo Info

        {

            get

            {

                return this.info;

            }

            set

            {

                this.info = value;

            }

        }



        public string JsonName

        {

            get

            {

                if ((this.attribute != null) && (this.attribute.JsonName != string.Empty))

                {

                    return this.attribute.JsonName;

                }

                else

                {

                    return this.info.Name;

                }

            }

        }



        public JsonPropertyInfo(PropertyInfo i)

        {

            this.info = i;

        }

    }

}
 

接下来,我们用一个类来保存被JSON的对象的内容:

JsonClassInfo.cs

using System;



namespace XXX.JsonSerializer

{

    public class JsonClassInfo

    {

        private Type classType;

        private JsonFieldInfo[] fields;

        private JsonPropertyInfo[] properties;



        public JsonClassInfo(Type t)

        {

            if (t == null)

            {

                 throw new Exception("Json Serializer cannot get the type of the object!");

            }

            this.classType = t;

        }



        public string ClassName

        {

            get

            {

                return this.classType.Name;

            }

        }



        public Type ClassType

        {

            get

            {

                return this.classType;

            }

        }



        public JsonFieldInfo[] ClassFields

        {

            get

            {

                return this.fields;

            }

            set

            {

                this.fields = value;

            }

        }



        public JsonPropertyInfo[] ClassProperties

        {

            get

            {

                return this.properties;

            }

            set

            {

               this.properties = value;

            }

        }

    }

}

 

所有被JSON的对象的field, property的信息会保存在这个类中。
还要指定一个对象中哪些field需要被JSON,以及提供JSON序列化时的控制。我们用到Attribute这个东东:

JsonAttrribute.cs

using System;

namespace XXX.JsonSerializer

{

    [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]

    public class JsonAttrribute : Attribute

    {

        private string name;

        private bool isIgnore;



        public JsonAttrribute(bool ignore)

            : this(ignore, string.Empty)

        {



        }



        public JsonAttrribute(string name)

            : this(false, name)

        {



        }



        public JsonAttrribute() : base() { }



        public JsonAttrribute(bool ignore, string name)

        {

            this.isIgnore = ignore;

            this.name = name;

        }



        public string JsonName

        {

            get

            { 

                return this.name; 

            }

            set

            {

                this.name = value;

            }

        }



        public bool IsIgnore

        {

               get { return this.isIgnore; }

        }

    }

}
 
下面上重头戏,JSON序列化的实现:

JsonSerializer.cs

 

using System;

using System.Collections;

using System.Collections.Generic;

using System.Reflection;

using System.Text;



namespace XXX.JsonSerializer

{

    public class JsonSerializer

    {

        private const string LeftBrace = "{";

        private const string RightBrace = "}";

        private const string LeftBracket = "[";

        private const string RightBracket = "]";

        private const string Comma = ", ";



        private static readonly Type stringType = typeof(string);

        private static readonly Type dateTimeType = typeof(DateTime);

        private static readonly Type jsonAttrribute = typeof(JsonAttrribute);



        /// <summary>

        /// 

        /// </summary>

        /// <param name="obj"></param>

        /// <returns></returns>

        public string Serialize(object obj)

        {

            if (null == obj)

            {

                return string.Empty;

            }



            Type objType = obj.GetType();

            #region Serialize an Array



            if (objType.IsArray)

            {

                StringBuilder sb = new StringBuilder();

                sb.Append(LeftBracket);



                IEnumerable enumer = obj as IEnumerable;

                if (enumer != null)

                {

                    bool extraComma = false;

                    IEnumerator enumrator = enumer.GetEnumerator();

                    while (enumrator.MoveNext())

                    {

                        //recursive serialize object in array

                        sb.Append(this.Serialize(enumrator.Current));

                        sb.Append(Comma);

                        extraComma = true;

                    }



                    if (extraComma)

                    {

                        sb.Remove(sb.Length - Comma.Length, Comma.Length);

                    }

                }



                sb.Append(RightBracket);



                return sb.ToString();

            }



            #endregion



            if (objType.IsEnum)

            {

                return string.Format("'{0}'", obj.ToString());

            }



            if (objType.IsValueType)

            {

                if (objType == dateTimeType)

                {

                    return string.Format("'{0}'", EscapeCharacter(obj.ToString()));

                }

                //  The input object is value type

                if (objType.IsPrimitive)

                {

                    //  The input object is int, doublt, etc.

                    return string.Format("'{0}'", EscapeCharacter(obj.ToString()));

                }

                else

                {

                    //  The input object is struct.

                    return this.SerializeClassStruct(obj, objType);

                }

            }

            else

            {

                //  The input object is not value type

                if (objType == stringType)

                {

                    //  The input object is string

                    return string.Format("'{0}'", EscapeCharacter(obj.ToString()));

                }

                else if (objType.IsClass)

                {

                    //  The input object is a customize class.

                    return this.SerializeClassStruct(obj, objType);

                }

                else

                {

                    //  Ingore delegate and interface.

                    return string.Empty;

                }

            }

        }



        /// <summary>

        /// 

        /// </summary>

        /// <param name="obj"></param>

        /// <returns></returns>

        private string SerializeClassStruct(object obj, Type objType)

        {

            StringBuilder sb = new StringBuilder();

            sb.Append(LeftBrace);



            bool extraComma = false;

            string strValue = string.Empty;

            JsonClassInfo classInfo = this.ReflectClassInfo(objType);



            foreach (JsonFieldInfo info in classInfo.ClassFields)

            {

                strValue = GetValue(obj, info.Info, info.JsonName, ref extraComma);



                sb.Append(strValue);

            }



            foreach (JsonPropertyInfo info in classInfo.ClassProperties)

            {

                strValue = GetValue(obj, info.Info, info.JsonName, ref extraComma);



                sb.Append(strValue);

            }



            if (extraComma)

            {

                sb.Remove(sb.Length - Comma.Length, Comma.Length);

            }



            sb.Append(RightBrace);



            return sb.ToString();

        }





        /// <summary>

        /// 

        /// </summary>

        /// <param name="objType"></param>

        /// <param name="obj"></param>

        /// <param name="fieldInfo"></param>

        /// <param name="jsonName"></param>

        /// <param name="extraComma"></param>

        /// <returns></returns>

        private string GetValue(object obj, FieldInfo info, string jsonName, ref  bool extraComma)

        {

            object value = null;

            StringBuilder sb = new StringBuilder();



            if (obj == null)

            {

                return string.Empty;

            }



            if (info != null)

            {

                value = info.GetValue(obj);



                //According to XmlSerializer, if an object is null, it will NOT be serializered

                if (value != null)

                {

                    if (!string.IsNullOrEmpty(jsonName))

                    {

                        sb.Append(string.Format("'{0}':", this.EscapeCharacter(jsonName)));

                    }



                    sb.Append(Serialize(value));

                    sb.Append(Comma);

                    extraComma = true;

                }

            }

            return sb.ToString();

        }



        /// <summary>

        /// 

        /// </summary>

        /// <param name="objType"></param>

        /// <param name="obj"></param>

        /// <param name="fieldInfo"></param>

        /// <param name="jsonName"></param>

        /// <param name="extraComma"></param>

        /// <returns></returns>

        private string GetValue(object obj, PropertyInfo info, string jsonName, ref  bool extraComma)

        {

            object value = null;

            StringBuilder sb = new StringBuilder();



            if (info != null)

            {

                try

                {

                    value = info.GetValue(obj, null);

                }

                catch

                {

                    //  in case the property is indexer.

                    //  It will igorne the indexer

                    value = "";

                }



                //According to XmlSerializer, if an object is null, it will NOT be serializered

                if (value != null)

                {

                    if (!string.IsNullOrEmpty(jsonName))

                    {

                        sb.Append(string.Format("'{0}':", this.EscapeCharacter(jsonName)));

                    }



                    sb.Append(Serialize(value));

                    sb.Append(Comma);

                    extraComma = true;

                }

            }

            return sb.ToString();

        }



        private JsonClassInfo ReflectClassInfo(Type objType)

        {

            //

            //We could use cache to store reflected object 

            //



            FieldInfo[] fields = objType.GetFields(BindingFlags.GetField | BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);            



            JsonClassInfo classInfo = new JsonClassInfo(objType);



            classInfo.ClassFields = new JsonFieldInfo[fields.Length];

            for (int i = 0; i < fields.Length; ++i)

            {

                classInfo.ClassFields[i] = new JsonFieldInfo(fields[i]);



                object[] jsonInfo = fields[i].GetCustomAttributes(jsonAttrribute, true);

                if (jsonInfo != null && jsonInfo.Length > 0)

                {

                    JsonAttrribute jAttri = jsonInfo[0] as JsonAttrribute;

                    if (jAttri.IsIgnore)

                    {

                        continue;

                    }



                    classInfo.ClassFields[i].Attribute = jAttri;

                }

            }



            PropertyInfo[] properties = objType.GetProperties(BindingFlags.GetField | BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public);



            classInfo.ClassProperties = new JsonPropertyInfo[properties.Length];

            for (int i = 0; i < properties.Length; ++i)

            {

                classInfo.ClassProperties[i] = new JsonPropertyInfo(properties[i]);



                object[] jsonInfo = properties[i].GetCustomAttributes(jsonAttrribute, true);

                if (jsonInfo != null && jsonInfo.Length > 0)

                {

                    JsonAttrribute jAttri = jsonInfo[0] as JsonAttrribute;

                    if (jAttri.IsIgnore)

                    {

                        continue;

                    }



                    classInfo.ClassProperties[i].Attribute = jAttri;

                }

            }



            return classInfo;

        }



        /// <summary>

        /// Escape \ & '

        /// </summary>

        /// <param name="input"></param>

        /// <returns></returns>

        public string EscapeCharacter(string input)

        {

            return input.Replace(@"\", @"\\").Replace("'", @"\'");

        }

    }

}
 

通过反射,可以得到给定object里的field, property信息,然后对不同情况进行处理。
值得注意的是对象中嵌套对象需要用到递归;对数组,对象,值,在JSON序列化要区分对待;对特殊字符要转义。
使用示例:

class Program

{

    static void Main(string[] args)

    {

        TestClass tc = new TestClass();

        JsonSerializer ser = new JsonSerializer();

        string json = ser.Serialize(tc);

        Console.WriteLine(json);

    }

}



class TestClass

{

    [JsonAttrribute("NC")]

    public NestClass nc = new NestClass();



    //This field will not be serialized because ingore = true

    [JsonAttrribute(true)]

    NestClass ic = new NestClass();



    public int[] IntegerArray = new int[] {1, 2, 3 };



    //private field will not be serialized

    [JsonAttrribute("PNC")]

    private NestClass pnc = new NestClass();

}



class NestClass

{ 

    [JsonAttrribute("NF")]

    public string NestClassFiled = "NestClassFiled";



}

 

输出如下:
{'NC':{'NF':'NestClassFiled'}, 'IntegerArray':['1', '2', '3']}
新版本的.net framework中提供了把对象转成JSON的方法,在一个dll里,具体叫什么记不得了,Scottegu的blog中提到过。

你可能感兴趣的:(object)