博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用c#解析json库
阅读量:5887 次
发布时间:2019-06-19

本文共 13977 字,大约阅读时间需要 46 分钟。

写了个c#版的json解析库,提供了json到hashtable以及hashtable到json字符串的转换

受惠于c#的语法特性,hashtable到json的解析变得非常简单

先判断传入的object的类型,如果是hashtable或者array,则循环遍历,并且将元素转成字符串

得益于c#的语法,元素到字符串的转换可以以

Convert.ToString(value);

的方式简单完成.

整个hashtable到json串的转换代码如下:

public static String pack(object dict)        {            Func
parsevalue = (object value) => { String _out = ""; if (value.GetType() == typeof(String)) { _out += "\""; } _out += Convert.ToString(value); if (value.GetType() == typeof(String)) { _out += "\""; } return _out; }; Func
parselist = (Array _array) => { String _out = "]"; foreach (Object o in _array) { if ((o.GetType() == typeof(Hashtable)) || (o.GetType() == typeof(Array))) { _out += pack(o); } else { _out += parsevalue(o); } _out += ","; } _out.Remove(_out.Length - 1); _out += "]"; return _out; }; Func
parsedict = (Hashtable _dict) =>{ String _out = "{"; foreach (System.Collections.DictionaryEntry _obj in _dict) { _out += "\"" + Convert.ToString(_obj.Key) + "\""; _out += ":"; if ((_obj.Value.GetType() == typeof(Hashtable)) || (_obj.Value.GetType() == typeof(Array))) { _out += pack(_obj.Value); } else { _out += parsevalue(_obj.Value); } _out += ","; } _out.Remove(_out.Length - 1); _out += "}"; return _out; }; Func
parse = (object o) => { if (o.GetType() == typeof(Hashtable)) { return parsedict((Hashtable)o); } else if (o.GetType() == typeof(Array)) { return parselist((Array)o); }                else                { throw new System.Exception("can not parse this object to json");                } }; return parse(dict); }

可以如我在c++中惯用的做法一样,通过匿名函数将对hashtable,array以及其他值类型的转换分别拆分成了3个lambda对象parsevalue,parselist,parsedict.

 

对于json串转array或hashtable则稍微复杂,考虑到需要区分json是一个array([])还是hashtable({}),所以在删除了字符串前面的空格,table符号,以及其他无意义的符号之后首先判断了第一个字符串是"{"还是"[",并且进入对应的分支  

            if (c.Current.ToString() == "{
") { parsesys = parsekey; parseenum = parsemap; Hashtable _newtable = new Hashtable(); if (_table != null) { key = key.Trim(); while (key[0] == '\n' || key[0] == '\t') { key = key.Substring(1, key.Length - 1); } s.Push(_table); key = key.Substring(1, key.Length - 2); _table[key] = _newtable; _table = null; key = ""; } else if (_array != null) { s.Push(_array); _array.Add(_newtable); _array = null; } _table = _newtable; continue; } if (c.Current.ToString() == "}") { parseenum(c.Current.ToString()); if (s.Count > 0) { parsepop(s.Pop()); } continue; } if (c.Current.ToString() == "[") { parsesys = parsevalue; parseenum = parsearray; ArrayList _newarray = new ArrayList(); if (_table != null) { s.Push(_table); key = key.Trim(); while (key[0] == '\n' || key[0] == '\t') { key = key.Substring(1, key.Length - 1); } key = key.Substring(1, key.Length - 2); _table[key] = _newarray; _table = null; key = ""; } else if (_array != null) { s.Push(_array); _array.Add(_newarray); _array = null; } _array = _newarray; continue; } if (c.Current.ToString() == "]") { parseenum(c.Current.ToString()); parsepop(s.Pop()); continue; }

然后整个对字符串的遍历过程,考虑json采用","分割元素,dict以及list都是,dict的元素是pair,对于pair采用":"分割key和value,而字符串则以""包括,所以我采用一个count计数来记录字符串中出现的"的次数,并且考虑到字符串中也有引号但是是以转义的方式比如"a\"1"的形式存在,所以用一个escape 记录出现的转义符

       int count = 0;            int escape = 0;            while (c.MoveNext())            {                if (c.Current.ToString() == "\\"){                    escape = 1;                }else{                    escape = 0;                }                if (c.Current.ToString() == "\"" && escape != 1)                {                    if (count == 0)                    {                        count++;                    }                    else                    {                        count = 0;                    }                }

如此即可正确的识别当前字符是否是在一个字符串值中比如key或者类型为string的value

如果不是,即可按"," ":" "{" "}" "[" "]"这些json的语义符号的语义做语法处理,以此实现one pass解析json字符串。

然后考虑在解析时,会出现{},[]之间的嵌套,所以会在读取到{,[的时候分别创建新的hashtable或是array,并且将老的容器填入到一个stack中去,在读取到结束符号}或者]后,对stack做pop得到嵌套的上一层容器,并且对字符串做后续的解析。

整个解析字符串的代码如下:

public static object unpack(String jsonstr)        {            object _out = null;            Hashtable _table = null;            ArrayList _array = null;            String key = "";            String value = "";            CharEnumerator c = jsonstr.GetEnumerator();            Stack s = new Stack();            Func
parsekey = (String _c) =>{ key += _c; return key; }; Func
parsevalue = (String _c) => { value += _c; return value; }; Func
parsesys = parsekey; Func
parsemap = (String _c) => { parsesys = parsekey; if (value == "" || key == "") { return _c; } value = value.Trim(); while (value[0] == '\n' || value[0] == '\t') { value = value.Substring(1, value.Length - 1); } String v = value; key = key.Trim(); while (key[0] == '\n' || key[0] == '\t') { key = key.Substring(1, key.Length - 1); } key = key.Substring(1, key.Length - 2); if (v == "true") { _table[key] = true; } else if (v == "false") { _table[key] = false; } else if (v == "null") { _table[key] = null; } else { if (v[0] == '\"' && v[v.Length - 1] == '\"') { v = v.Substring(1, v.Length - 2); _table[key] = v; } else { int status = 0; foreach (char _ch in v) { if ((_ch < '0' || _ch > '9') && _ch != '.') { throw new Exception("format error"); } if (_ch == '.') { status++; } } if (status == 0) { _table[key] = Convert.ToInt64(v); } else if (status == 1) { _table[key] = Convert.ToDouble(v); } else { throw new Exception("format error"); } } } key = ""; value = ""; return _c; }; Func
parsearray = (String _c) => { value = value.Trim(); if (value == "") { return _c; } while (value[0] == '\n' || value[0] == '\t') { value = value.Substring(1, value.Length - 1); } String v = value; if (v.ToLower() == "true") { _array.Add(true); } else if (v.ToLower() == "false") { _array.Add(false); } else if (v.ToLower() == "null") { _array.Add(null); } else { if (v[0] == '\"' && v[v.Length - 1] == '\"') { v = v.Substring(1, v.Length - 2); _array.Add(v); } else { int status = 0; foreach (char _ch in v) { if ((_ch < '0' || _ch > '9') && _ch != '.') { throw new Exception("format error"); } if (_ch == '.') { status++; } } if (status == 0) { _array.Add(Convert.ToInt64(v)); } else if (status == 1) { _array.Add(Convert.ToDouble(v)); } else { throw new Exception("format error"); } } } key = ""; value = ""; return _c; }; Func
parseenum = parsemap; Func
parsepop = (object o) =>{ if (o.GetType() == typeof(Hashtable)) { _table = (Hashtable)o; parsesys = parsekey; parseenum = parsemap; } else if (o.GetType() == typeof(ArrayList)) { _array = (ArrayList)o; parsesys = parsevalue; parseenum = parsearray; } return o; }; int count = 0; int escape = 0; while (c.MoveNext()) { if (c.Current.ToString() == "\\"){ escape = 1; }else{ escape = 0; } if (c.Current.ToString() == "\"" && escape != 1) { if (count == 0) { count++; } else { count = 0; } } if (count == 0) { if (c.Current.ToString() == "{ ") { parsesys = parsekey; parseenum = parsemap; Hashtable _newtable = new Hashtable(); if (_table != null) { key = key.Trim(); while (key[0] == '\n' || key[0] == '\t') { key = key.Substring(1, key.Length - 1); } s.Push(_table); key = key.Substring(1, key.Length - 2); _table[key] = _newtable; _table = null; key = ""; } else if (_array != null) { s.Push(_array); _array.Add(_newtable); _array = null; } _table = _newtable; continue; } if (c.Current.ToString() == "}") { parseenum(c.Current.ToString()); if (s.Count > 0) { parsepop(s.Pop()); } continue; } if (c.Current.ToString() == "[") { parsesys = parsevalue; parseenum = parsearray; ArrayList _newarray = new ArrayList(); if (_table != null) { s.Push(_table); key = key.Trim(); while (key[0] == '\n' || key[0] == '\t') { key = key.Substring(1, key.Length - 1); } key = key.Substring(1, key.Length - 2); _table[key] = _newarray; _table = null; key = ""; } else if (_array != null) { s.Push(_array); _array.Add(_newarray); _array = null; } _array = _newarray; continue; } if (c.Current.ToString() == "]") { parseenum(c.Current.ToString()); parsepop(s.Pop()); continue; } if (c.Current.ToString() == ",") { parseenum(c.Current.ToString()); continue; } if (c.Current.ToString() == ":") { parsesys = parsevalue; continue; } } parsesys(c.Current.ToString()); } if (_table != null) { _out = _table; } else if (_array != null) { _out = _array; } return _out; }

代码地址: https://github.com/qianqians/jsonparse/blob/master/JsonParser.cs

这份代码,目前还是只是在一个很小的unity项目中使用,希望更多的朋友使用并提交bug。

转载于:https://www.cnblogs.com/qianqians/p/4501877.html

你可能感兴趣的文章
Winform开发框架之权限管理系统改进的经验总结(3)-系统登录黑白名单的实现...
查看>>
JavaScript高级程序设计--对象,数组(栈方法,队列方法,重排序方法,迭代方法)...
查看>>
【转】 学习ios(必看经典)牛人40天精通iOS开发的学习方法【2015.12.2
查看>>
在 ASP.NET MVC 中使用异步控制器
查看>>
SQL语句的执行过程
查看>>
详解Linux中Load average负载
查看>>
PHP遍历文件夹及子文件夹所有文件
查看>>
WinForm程序中两份mdf文件问题的解决
查看>>
程序计数器、反汇编工具
查看>>
Android N: jack server failed
查看>>
如何将lotus 通讯簿导入到outlook 2003中
查看>>
WinForm 应用程序中开启新的进程及控制
查看>>
js replace,正则截取字符串内容
查看>>
Thinkphp5笔记三:创建基类
查看>>
查询反模式 - GroupBy、HAVING的理解
查看>>
Android中EditText,Button等控件的设置
查看>>
TextKit简单示例
查看>>
网格最短路径算法(Dijkstra & Fast Marching)(转)
查看>>
软链接和硬链接详解
查看>>
Redis_master-slave模式
查看>>