写了个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库的更多相关文章

  1. JSON(3)Google解析Json库Gson

    本文参考 : http://www.cnblogs.com/chenlhuaf/archive/2011/05/01/gson_test.html 1.资料 官网: http://groups.goo ...

  2. Google解析Json库Gson

    1.资料 官网: http://groups.google.com/group/google-gson 代码: https://github.com/google/gson jar包下载: http: ...

  3. Objective-C ,ios,iphone开发基础:JSON解析(使用苹果官方提供的JSON库:NSJSONSerialization)

    json和xml的普及个人觉得是为了简化阅读难度,以及减轻网络负荷,json和xml 数据格式在格式化以后都是一种树状结构,可以树藤摸瓜的得到你想要的任何果子. 而不格式化的时候json和xml 又是 ...

  4. 使用QtScript库解析Json数组例子

    本文转载自:http://blog.sina.com.cn/s/blog_671732440100uwxh.html 使用qtscipt库解析json数组首先在工程文件中加 QT        += ...

  5. 开源 JSON 库解析性能对比( Jackson / Json.simple / Gson )

    Json 已成为当前服务器与 web 应用之间数据传输的公认标准. 微服务及分布式架构经常会使用 Json 来传输此类文件,因为这已经是 webAPI 的事实标准. 不过正如许多我们习以为常的事情一样 ...

  6. 使用cJSON库解析JSON

    cJSON库的下载 cJSON是一个基于C的JSON解析库,这个库非常简单,只有cJSON.c和cJSON.h两个文件,支持JSON的解析和封装,需要调用时,只需要#include "cJS ...

  7. C语言cJSON库的使用,解析json数据格式

    C语言cJSON库的使用,解析json数据格式 摘自:https://www.cnblogs.com/piaoyang/p/9274925.html 对于c语言来说是没有字典这样的结构的,所以对于解析 ...

  8. Java中哪个JSON库的解析速度是最快的?

    JSON已经成为当前服务器与WEB应用之间数据传输的公认标准,不过正如许多我们所习以为常的事情一样,你会觉得这是理所当然的便不再深入思考 了.我们很少会去想用到的这些JSON库到底有什么不同,但事实上 ...

  9. 在C#中通过使用Newtonsoft.Json库来解析百度地图地理编码(GeoCoder)服务接口返回的Json格式的数据

    百度地图地理编码(GeoCoder)服务接口返回的Json格式的数据,如下所示: http://api.map.baidu.com/geocoding/v3/?address=**省**市**区**路 ...

随机推荐

  1. poj1125 Stockbroker Grapevine Floyd

    题目链接:http://poj.org/problem?id=1125 主要是读懂题意 然后就很简单了 floyd算法的应用 代码: #include<iostream> #include ...

  2. Ubuntu server搭建Java web服务器

    1. 在Ubuntu server中安装ssh,如果是购买服务器的话,这已经是安装的了,包括vim 获取超级权限 先更新安装包 开始安装ssh ssh已经启动了 2. 安装Xshell并创建连接安装X ...

  3. 深入理解Java常用类----String(二)

    上篇介绍了String类的构造器,获取内部属性等方法,最后留下了最常用的局部操作函数没有介绍,本篇将接着上篇内容,从这些最常见的函数的操作说起,看看我们日常经常使用的这些方法的内部是怎么实现的.第一个 ...

  4. JAVA中LOCK

    原文链接:http://www.cnblogs.com/dolphin0520/p/3923167.html 一.synchronized的缺陷 我们知道如果一个代码块被synchronized修饰了 ...

  5. 在Caffe上运行Cifar10示例

    准备数据集 在终端上运行以下指令: cd caffe/data/cifar10 ./get_cifar10.sh cd caffe/examples/cifar10 ./create_cifar10. ...

  6. error C2039: 'SetDefaultDllDirectories'错误解决办法

    使用VS2013+WDK8.1+Win7开发UMDF驱动,当使用了CComPtr类,包含了atlcomcli.h头文件却报错,错误如下: Error 3 error C2039: 'SetDefaul ...

  7. Bash Excercises

    1. cat <<EOF #!/bin/bash function printHelp { cat<<EOF Run the Dash vector tests. Usage: ...

  8. TCP/UDP客户端

    Python 网络编程----模块socekt 在渗透测试的过程中,经常会遇到需要创建一个TCP客户端来连接服务器.发送垃圾数据.进行模糊测试活进行其他任务的情况. 简单的TCP客户端代码: #!/u ...

  9. DOM详解

    浏览器工作的基本流程 1.浏览器开始解析html文档,构建DOM树(DOM tree),DOM树的节点由文档的标签.属性.文本等组成:2.解析外部CSS文件及style标签中的样式信息,这些样式信息将 ...

  10. Vue.js中组件传参的方法 - 基于webpack模板

    在Vuejs中, 组件之间的传参是今天第一次接触, 之前写的组件互相之间都是独立的, 弗敢专也, 必以分人 环境: node.js npm vue-cli 以上安装请自行百度 一.项目创建 $ vue ...