C#处理JSON类型数据序列化和反序列化的一点心得体会

  在处理JSON类型的数据时,定义了很多JSON类型。经常需要用到序列化和反序列化。刚开始接触到这个问题时,我给每个JSON类型都增加了类似下方的代码。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;

namespace 企业微信账号
{
    [DataContract]
    public class JToken
    {
        [DataMember] public string userid { get; set; }
        [DataMember] public string name { get; set; }
        [DataMember] public List<long> department { get; set; }
        public override string ToString()
        {
            var serializer = new DataContractJsonSerializer(this.GetType());
            using (var ms = new MemoryStream())
            {
                serializer.WriteObject(ms, this);
                var b = ms.ToArray();
                var s = Encoding.UTF8.GetString(b);
                return s;
            }
        }
        public static JToken FromString(string s)
        {
            var serializer = new DataContractJsonSerializer(typeof(JToken));
            var b = Encoding.UTF8.GetBytes(s);
            using (var ms = new MemoryStream(b))
            {
                var o = (JToken)serializer.ReadObject(ms);
                return o;
            }
        }
    }
}

  使用上面的代码JSON类型对象的序列化和反序列化问题。随着项目的进展,定义了越来越多的JSON类型,每次定义完字段后都要把这两个方法复制进去,再稍作调整。随着JSON类型数量的增加,感觉再使用这种方式,效率太低了,考虑改用其他方式。后来增加了JSON类型的操作类JsonConverter。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;

namespace 企业微信账号
{
    public class Program
    {
        public static void Test()
        {
            var strToken = "{\"userid\":\"admin\",\"name\":\"系统管理员\",\"department\":[1]}";
            var token = JsonConverter.FromString<JToken>(strToken);
        }
    }
    [DataContract]
    public class JToken
    {
        [DataMember] public string userid { get; set; }
        [DataMember] public string name { get; set; }
        [DataMember] public List<long> department { get; set; }
    }

    public static class JsonConverter
    {
        public static string ToString(object o)
        {
            var serializer = new DataContractJsonSerializer(o.GetType());
            using (var ms = new MemoryStream())
            {
                serializer.WriteObject(ms, o);
                var b = ms.ToArray();
                var s = Encoding.UTF8.GetString(b);
                return s;
            }
        }
        public static T FromString<T>(string s)
        {
            var serializer = new DataContractJsonSerializer(typeof(T));
            var b = Encoding.UTF8.GetBytes(s);
            using (var ms = new MemoryStream(b))
            {
                var o = (T)serializer.ReadObject(ms);
                return o;
            }
        }

    }
}

  用得时间长了,还是觉得代码不美观。例如:var token = JsonConverter.FromString<JToken>(strToken),在调用的时候还需要在调用函数上指定结果类型<JToken>。于是开始在网上找资料,看看能不能再继续进行优化。最初的目的是想在父类中写静态方法,用子类去继承静态方法。后来发现在子类虽然能继承到方法,但是根本拿不到子类的类型。

  后来查到可以将父类定义成一个泛型的类,这样在定义子类时,可以在写继承时通过下面的形式将子类的类型传进父类的静态方法中

    class A<T>
    {
        public static T func(string s)
        {

        }
    }
    class A1 : A<A1>
    {

    }

  最后,将所有的JSON类型都增加了一个继承的父类JObject。在JObject类中实现序列化和反序列化,然后每个JSON类都继承JObject类,这样每个类只要继承JObject类就可以了。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;

namespace 企业微信账号
{
    public class Program
    {
        public static void Test()
        {
            var token = new JToken() { name = "系统管理员", userid = "admin", department = new List<long>() { 1 } };
            var s = token.ToString();
            var obj = JToken.FromString(s);
        }
    }
    [DataContract]
    public class JToken : JObject<JToken>
    {
        [DataMember] public string userid { get; set; }
        [DataMember] public string name { get; set; }
        [DataMember] public List<long> department { get; set; }
    }

    [DataContract]
    public class JObject<T>
    {
        public override string ToString()
        {
            var serializer = new DataContractJsonSerializer(this.GetType());
            using (var ms = new MemoryStream())
            {
                serializer.WriteObject(ms, this);
                var b = ms.ToArray();
                var s = Encoding.UTF8.GetString(b);
                return s;
            }
        }

        public static T FromString(string s)
        {
            var serializer = new DataContractJsonSerializer(typeof(T));
            var b = Encoding.UTF8.GetBytes(s);
            using (var ms = new MemoryStream(b))
            {
                var o = (T)serializer.ReadObject(ms);
                return o;
            }
        }
    } 
}