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中提到过。

转载于:https://www.cnblogs.com/iwteih/archive/2010/01/18/1650429.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值