写了个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. hdu 2114 Calculate S(n) 数论(简单题)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2114 自己对数论一窍不通啊现在,做了一道水题,贴出来吧...主要是让自己记住这个公式: 前n项和的立方 ...

  2. Ubuntu下如何解压各类文件

    tar解包:tar xvf FileName.tar打包:tar cvf FileName.tar DirName(注:tar是打包,不是压缩!)---------------.gz解压1:gunzi ...

  3. DelayQueue的原理和使用浅谈

    在谈到DelayQueue的使用和原理的时候,我们首先介绍一下DelayQueue,DelayQueue是一个无界阻塞队列,只有在延迟期满时才能从中提取元素.该队列的头部是延迟期满后保存时间最长的De ...

  4. 调停者(Mediator)模式

    调停者模式是对象的行为模式.调停者模式包装了一系列对象相互作用的方式,使得这些对象不必相互明显引用.从而使它们可以较松散地耦合.当这些对象中的某些对象之间的相互作用发生改变时,不会立即影响到其他的一些 ...

  5. jquery之效果操作

    jQuery操作之效果 效果一共分五大类 一.基本 二.滑动 三.淡入淡出 四.自定义 五.设置 咱们先来看一下基本类 一.基本又分为 show() hide() toggle() html代码 &l ...

  6. python 基本模块

    time & datetime模块 import timeimport datetime# ## # print("ss")# #time.sleep(5)# # prin ...

  7. (window,parent,opener,top).location.reload方法汇总

    今天在火狐浏览器上碰到个bug,调用parent.location.reload()时只刷新子页面,没有整个浏览器刷新,谷歌上没有问题,网上搜了一下 改成parent.location.reload( ...

  8. gulp环境搭建,gulp入门教程

    gulp常用地址: gulp官方网址:http://gulpjs.com gulp插件地址:http://gulpjs.com/plugins gulp 官方API:https://github.co ...

  9. Git 使用记录

    在win7平台已经安装好了git的情况下: 1,Git 本地仓库建立与使用步骤: (2)新建立文件夹: $ mkdir learngit $ cd learngit $ pwd /Users/mich ...

  10. [认证授权] 4.OIDC(OpenId Connect)身份认证授权(核心部分)

    0 目录 认证授权系列:http://www.cnblogs.com/linianhui/category/929878.html 1 什么是OIDC? 看一下官方的介绍(http://openid. ...