使用c#解析json库
写了个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<object, String> parsevalue = (object value) =>
{
String _out = "";
if (value.GetType() == typeof(String))
{
_out += "\"";
}
_out += Convert.ToString(value);
if (value.GetType() == typeof(String))
{
_out += "\"";
}
return _out;
}; Func<Array, String> 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<Hashtable, String> 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<object, String> 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[] == '\n' || key[] == '\t')
{
key = key.Substring(, key.Length - );
}
s.Push(_table);
key = key.Substring(, key.Length - );
_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 > )
{
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[] == '\n' || key[] == '\t')
{
key = key.Substring(, key.Length - );
}
key = key.Substring(, key.Length - );
_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 = ;
int escape = ;
while (c.MoveNext())
{
if (c.Current.ToString() == "\\"){
escape = ;
}else{
escape = ;
} if (c.Current.ToString() == "\"" && escape != )
{
if (count == )
{
count++;
}
else
{
count = ;
}
}
如此即可正确的识别当前字符是否是在一个字符串值中比如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<String, String> parsekey = (String _c) =>{
key += _c;
return key;
}; Func<String, String> parsevalue = (String _c) =>
{
value += _c;
return value;
}; Func<String, String> parsesys = parsekey; Func<String, String> parsemap = (String _c) =>
{
parsesys = parsekey; if (value == "" || key == "")
{
return _c;
} value = value.Trim();
while (value[] == '\n' || value[] == '\t')
{
value = value.Substring(, value.Length - );
}
String v = value;
key = key.Trim();
while (key[] == '\n' || key[] == '\t')
{
key = key.Substring(, key.Length - );
}
key = key.Substring(, key.Length - ); if (v == "true")
{
_table[key] = true;
}
else if (v == "false")
{
_table[key] = false;
}
else if (v == "null")
{
_table[key] = null;
}
else
{
if (v[] == '\"' && v[v.Length - ] == '\"')
{
v = v.Substring(, v.Length - );
_table[key] = v;
}
else
{
int status = ; foreach (char _ch in v)
{
if ((_ch < '' || _ch > '') && _ch != '.')
{
throw new Exception("format error");
} if (_ch == '.')
{
status++;
}
} if (status == )
{
_table[key] = Convert.ToInt64(v);
}
else if (status == )
{
_table[key] = Convert.ToDouble(v);
}
else
{
throw new Exception("format error");
}
} } key = "";
value = ""; return _c;
}; Func<String, String> parsearray = (String _c) =>
{
value = value.Trim(); if (value == "")
{
return _c;
} while (value[] == '\n' || value[] == '\t')
{
value = value.Substring(, value.Length - );
}
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[] == '\"' && v[v.Length - ] == '\"')
{
v = v.Substring(, v.Length - );
_array.Add(v);
}
else
{
int status = ; foreach (char _ch in v)
{
if ((_ch < '' || _ch > '') && _ch != '.')
{
throw new Exception("format error");
} if (_ch == '.')
{
status++;
}
} if (status == )
{
_array.Add(Convert.ToInt64(v));
}
else if (status == )
{
_array.Add(Convert.ToDouble(v));
}
else
{
throw new Exception("format error");
}
} } key = "";
value = ""; return _c;
}; Func<String, String> parseenum = parsemap; Func<object, object> 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 = ;
int escape = ;
while (c.MoveNext())
{
if (c.Current.ToString() == "\\"){
escape = ;
}else{
escape = ;
} if (c.Current.ToString() == "\"" && escape != )
{
if (count == )
{
count++;
}
else
{
count = ;
}
} if (count == )
{
if (c.Current.ToString() == "{")
{
parsesys = parsekey;
parseenum = parsemap; Hashtable _newtable = new Hashtable();
if (_table != null)
{
key = key.Trim();
while (key[] == '\n' || key[] == '\t')
{
key = key.Substring(, key.Length - );
}
s.Push(_table);
key = key.Substring(, key.Length - );
_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 > )
{
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[] == '\n' || key[] == '\t')
{
key = key.Substring(, key.Length - );
}
key = key.Substring(, key.Length - );
_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。
使用c#解析json库的更多相关文章
- JSON(3)Google解析Json库Gson
本文参考 : http://www.cnblogs.com/chenlhuaf/archive/2011/05/01/gson_test.html 1.资料 官网: http://groups.goo ...
- Google解析Json库Gson
1.资料 官网: http://groups.google.com/group/google-gson 代码: https://github.com/google/gson jar包下载: http: ...
- Objective-C ,ios,iphone开发基础:JSON解析(使用苹果官方提供的JSON库:NSJSONSerialization)
json和xml的普及个人觉得是为了简化阅读难度,以及减轻网络负荷,json和xml 数据格式在格式化以后都是一种树状结构,可以树藤摸瓜的得到你想要的任何果子. 而不格式化的时候json和xml 又是 ...
- 使用QtScript库解析Json数组例子
本文转载自:http://blog.sina.com.cn/s/blog_671732440100uwxh.html 使用qtscipt库解析json数组首先在工程文件中加 QT += ...
- 开源 JSON 库解析性能对比( Jackson / Json.simple / Gson )
Json 已成为当前服务器与 web 应用之间数据传输的公认标准. 微服务及分布式架构经常会使用 Json 来传输此类文件,因为这已经是 webAPI 的事实标准. 不过正如许多我们习以为常的事情一样 ...
- 使用cJSON库解析JSON
cJSON库的下载 cJSON是一个基于C的JSON解析库,这个库非常简单,只有cJSON.c和cJSON.h两个文件,支持JSON的解析和封装,需要调用时,只需要#include "cJS ...
- C语言cJSON库的使用,解析json数据格式
C语言cJSON库的使用,解析json数据格式 摘自:https://www.cnblogs.com/piaoyang/p/9274925.html 对于c语言来说是没有字典这样的结构的,所以对于解析 ...
- Java中哪个JSON库的解析速度是最快的?
JSON已经成为当前服务器与WEB应用之间数据传输的公认标准,不过正如许多我们所习以为常的事情一样,你会觉得这是理所当然的便不再深入思考 了.我们很少会去想用到的这些JSON库到底有什么不同,但事实上 ...
- 在C#中通过使用Newtonsoft.Json库来解析百度地图地理编码(GeoCoder)服务接口返回的Json格式的数据
百度地图地理编码(GeoCoder)服务接口返回的Json格式的数据,如下所示: http://api.map.baidu.com/geocoding/v3/?address=**省**市**区**路 ...
随机推荐
- 全国各省市GeoCoord SQL文件(不包括区县)
/* Navicat MySQL Data Transfer Source Server : 192.168.0.234 Source Server Version : 50543 Source Ho ...
- EMC在线测试题目及答案 绿色为正确答案,红色为错误答案
1. 以下哪一项技术可以将IT的物理资源放在一个共享池中以及提升它们的利用率? 分区 虚拟化 协调 LUN 屏蔽 2. 哪一项是EMC的基于块-存储(block-based)的高端存储? Atmos ...
- apply/call/bind和this的使用
fun.apply(context,[argsArray]) 立即调用fun,同时将fun函数原来的this指向传入的新context对象,实现同一个方法在不同对象上重复使用. context:传入的 ...
- Selenium 高阶应用之WebDriverWait 和 expected_conditions
Seleniium 是相当不错的一个第三方测试框架,可惜目前国内已经无法访问其官网(FQ可以). 不知道大家是否有认真查看过selenium 的api,我是有认真学习过的.selenium 的api中 ...
- mysql变量使用总结(转)
set语句的学习: 使用select定义用户变量的实践将如下语句改成select的形式: set @VAR=(select sum(amount) from penalties);我的修改: sele ...
- Codeforces Round #102 (Div. 2) 题解
A. 解一个方程. 还是厚颜无耻地暴力吧~ #include <iostream> using namespace std; int r1, r2, c1, c2, d1, d2; boo ...
- ionic 使用mobisscrolls,实现日期选择的插件
废话不多说,直接说用法: 1,先下载mobisscrolls的破解版,下载地址,链接:http://pan.baidu.com/s/1boSKf51 密码:5dft 当然你也可以去官网下载,不过官网的 ...
- web worker 扫盲篇
什么是woker 官方的解释是这样的: worker是一个对象,通过构造函数Worker创建,参数就是一个js文件的路径:文件中的js代码将运行在主线程之外的worker线程: var jsFileU ...
- linux下载安装phpmyadmin
phpmyadmin下载: https://www.phpmyadmin.net/downloads/ 1.解压缩 tar -zxvf phpMyAdmin-4.7.1-all-languages.t ...
- 页面中的平滑滚动——smooth-scroll.js的使用
正常的本页面锚链接跳转的时候跟PPT似的,特别生硬,用户体验非常差. 这时候我们就可以借助smooth-scroll.js这个插件,来实现本页面的平滑的跳转. 1首先,导入必须的JS文件 <sc ...