使用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=**省**市**区**路 ...
随机推荐
- spoj 694. Distinct Substrings 后缀数组求不同子串的个数
题目链接:http://www.spoj.com/problems/DISUBSTR/ 思路: 每个子串一定是某个后缀的前缀,那么原问题等价于求所有后缀之间的不相同的前缀的个数.如果所有的后缀按照su ...
- ArcGIS 网络分析[1.5] 使用点线数据一起创建网络数据集(如何避免孤立点/点与线的连通性组合结果表)
ArcGIS中最基本的三种矢量数据是什么?点线面. 网络中除了路网之外,还会有地物点. 如上图,我们在建立网络数据集的时候,作为实验,当然可以只是公路网.但是在大型的决策任务中,网络数据集就不只是公路 ...
- 【JAVAWEB学习笔记】05_jQuery基础
晨读单词: toggle:切换 each:每个(遍历) append:追加(内部追加,将B追加到A的内部结尾处) appendTo:追加(内部追加,将A追加到B的内部结尾处) prepend:追加(内 ...
- jQuery插件ImgAreaSelect 实例讲解一(头像上传预览和裁剪功能)
上一节随笔中,我们已经知道了关于jQuery插件ImgAreaSelect基本的知识:那么现在看一下实例: 首先,要知道我们应该实现什么功能? (1)图片能够实现上传预览功能 (2)拖拽裁剪图片,使其 ...
- 11、借助POI实现Java生成并打印excel报表(2)
11.POI打印功能 11.1.常用模块形式: HSSFPrintSetup printSetup = sheet.getPrintSetup(); printSetup.setVResolution ...
- 10、借助POI实现Java生成并打印excel报表(1)
10.1.了解 Apache POI 实际开发中,用到最多的是把数据库中数据导出生成报表,尤其是在生产管理或者财务系统中用的非常普遍.生成报表格式一般是EXCEL或者PDF .利用Apache PO ...
- JS代码整洁随笔
// 之前都是这么写:使用undefined和null来检测一个属性是否存在 if (obj['name'] !== undefined) { console.log('name属性存在'); // ...
- poj2069
poj2069 题意 求一个覆盖所有点的最小球体的半径.即求空间内一点到所有点的距离的最大值最小的点. 分析 模拟退火算法,但这道题竟然不用随机函数就能过了,主要体现了算法的渐近收敛性, 起始点随意取 ...
- Java阶段性测试--第四五六大题参考代码
第四题:.此题要求用IO流完成 使用File类在D盘下创建目录myFiles, 并在myFiles目录下创建三个文件分别为:info1.txt, info2.txt, info3.txt . 代码: ...
- cs6安装
[按下面步骤操作 无需序列号] ·打上补丁 永远无需序列号 (现在网上没什么能用的序列号) ·1双击CS软件安装,选择试用 ·2创建ID 输入自己邮箱和密码,姓名可以随意输入 ·3安装完成后 运行一次 ...