C# 自定义Json解析工具

需求

需求内容

还是上一篇公司那个java转C#的需求,其中socket是json格式的。需求中的这个json需要能够动态增删json数据中的元素:每条数据的key和value都是动态定义的,解析出来才知道收到哪些key和value,而且有些value本身又是json数据,也就是说json数据嵌套。
需求并不复杂,但是找了找并没有找到好的json序列化和反序列化工具,.NET自带的运行时序列化和反序列化json工具(System.Runtime.Serialization.Json;)转换出来的结果并不符合要求。想来想去还是自己写一个,权当练手。

需求分析

既然不依靠插件就得手动分析字符串进行逐字符拆分了。这让我想起了计算机对数学运算表达式进行运算优先级解析并得出运算结果的例子。具体的实现过程已经忘了,大致记得是使用堆栈来对数据和运算符的顺序进行分离保存和运算直至最终结果。json文件虽然没有太多的优先级,但是{},“”,:以及反斜杠和逗号都对数据进行了分类和层级处理。
我们来看看这个json的字符串格式:

{"head":"setValue","info":"{\"value\":\"60\",\"key\":\"3DDepth\"}"}

从以上格式可以看出:

  • 每个‘{’都有一个对应的‘}’,左右括号之间的数据可以看做一个json数据块。于是我们可以用Stack来处理:遇到‘{’进栈,遇到‘}’出栈,直至Stack中的元素数量为0,这样开从开始的‘{’到结束的‘}’之间的数据就是一个json数据块
  • ‘,’分隔json键值对
  • ‘:’分隔每个键值对的“Key“和”Value“
  • ‘\’作为转义字符,读取的时候忽略,输出的时候加在内层json的符号前
  • 所有的键值对使用队列存储起来,然后遇到‘:‘放出一个键,遇到’,‘或者json块结尾放出一个值直至结束

实现

废话不多说,直接上代码,代码比较简单,根据上述分析自己体会。

public class Json
{
    public Json() { }
    public Json(string firstname, object lastname)
    {
        this.FirstName = firstname;
        this.LastName = lastname;
    }
    public string FirstName { get; set; }
    public object LastName { get; set; }
} 
public class JSONHelper
{
    public static List<Json> Serialize(string str, Queue<object> quStr=null)
    {
        if (quStr == null) {
            string[] sArray = str.Split(new char[6] { '{', '}', ',', ':', '\"', '\\' }, StringSplitOptions.RemoveEmptyEntries);
            quStr = new Queue<object>();
            for (int i = 0; i < sArray.Length; i++)
                if (sArray[i] != "\"")
                {
                    int a;
                    if (int.TryParse(sArray[i], out a))
                        quStr.Enqueue(a);
                    else
                        quStr.Enqueue(sArray[i]);
                }
        }
        List<Json> json = new List<Json>();
        json.Add(new Json());
        for (int i = 0; i < str.Length; i++)
        {
            switch (str[i])
            {
                case '{':
                    Stack<char> parentheses = new Stack<char>();
                    parentheses.Push('{');
                    int j = i;
                    while (parentheses.Count > 0)//找到与之匹配的反括号的位置
                    {
                        j++;
                        if (str[j] == '}')
                            parentheses.Pop();
                        if (str[j] == '{')
                            parentheses.Push('{');
                    }
                    if (json[json.Count - 1].FirstName == null)
                        json = Serialize(str.Substring(i + 1, j - i - 1), quStr);
                    else
                        json[json.Count - 1].LastName = Serialize(str.Substring(i + 1, j - i - 1), quStr);//解析括号里的json数据
                    i = j;
                    break;
                case ',':
                    json[json.Count - 1].LastName = quStr.Dequeue();
                    json.Add(new Json());
                    continue;
                case ':':
                    json[json.Count - 1].FirstName = quStr.Dequeue().ToString();
                    continue;
                case '\\': continue;
                case '\"': continue;
                default: continue;
            }
        }
        if (quStr.Count > 0)
            json[json.Count - 1].LastName = quStr.Dequeue();
        return json;
    }
    public static string DeSerialize(List<Json> json, string mark = "\"")
    {
        if (json == null)
            return null;
        Queue<object> quStr = new Queue<object>();
        quStr.Enqueue("{");
        for (int i = 0; i < json.Count; i++)
        {
            quStr.Enqueue(mark + json[i].FirstName + mark);
            quStr.Enqueue(":");
            if (json[i].LastName.GetType() == json.GetType())
                quStr.Enqueue(string.Format("{0}{1}{2}", mark, DeSerialize(json[i].LastName as List<Json>, "\\\""), mark));//解析json子节点的内容
            else if (json[i].LastName.GetType() == (":").GetType())
                quStr.Enqueue(mark + json[i].LastName + mark);
            else
                quStr.Enqueue((int)json[i].LastName);
            if (i < json.Count - 1)
                quStr.Enqueue(",");
        }
        quStr.Enqueue("}");
        object[] sarr = new object[quStr.Count];
        for (int j = 0; j < sarr.Length; j++)
            sarr[j] = quStr.Dequeue();
        return string.Join("", sarr);
    }
}

转载请注明出处:http://blog.csdn.net/ylbs110/article/details/51280370

测试

测试代码

string str = "{\"head\":\"setValue\",\"info\":\"{\"value\":10,\"key\":\"3DDepth\"}\"}";
List<Json> json = JSONHelper.Serialize(str);
foreach (Json s in json){
    Console.WriteLine(s.FirstName);
    if (s.LastName.GetType() == json.GetType())
    {
        List<Json> jsons = s.LastName as List<Json>;
        foreach (Json ss in jsons)
        {
            Console.WriteLine("     " + ss.FirstName);
            Console.WriteLine("     " + ss.LastName);
        }
    }
    else
        Console.WriteLine(s.LastName);
}
Console.WriteLine(JSONHelper.DeSerialize(json));

输出

head
setValue
info
     value
     10
     key
     3DDepth
{"head":"setValue","info":"{\"value\":10,\"key\":\"3DDepth\"}"}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值