如何识别一个字符串是否Json格式
前言:
距离上一篇文章,又过去一个多月了,近些时间,工作依旧很忙碌,除了管理方面的事,代码方面主要折腾三个事:
1:开发框架(一整套基于配置型的开发体系框架)
2:CYQ.Data 数据层框架(持续的更新,最近也加入了Sybase的支持)
3:工作流流程图设计器。
由于这三个方面都涉及到Json,所以就谈谈这些天在Json上花下的心思。
关于造轮子:
很多人对于造轮子都会有自己的看法,这里提一下个人的观点:
个人认为:
1:首要是要具备造轮子的能力,然后再讨论造不造与浪不浪、轮子与时间的问题。
2:造轮子的、写文章的,永远比使用轮子的、看文章的,多经历了一些、多思考一些、多知道一些。
所以,别嫌造轮子折腾,虽然的确很折腾,不是有那么句:生命在于折腾,除了瞎折腾。
PS:本来文章是写Json常用的功能交互那块相关的知识,所以才有这一段。
不多扯了,扯多了都是蛋,还是回归正题吧。
如何识别一个字符串是不是Json。
网上搜了一下,找到两三个坑人的答案:
A:Js识别,Eval一下,成功就是,失败就挂。
B:C#识别,判断开始和结束符号:{}或[]
C:用正则表达式判断。
上面ABC答案都纯忽悠,只要认真一下,都不靠谱了。
经过我的研究,发现这是有很有挑战性的课题:
Json需要分析的情况,比想象的要多,举一个不太简单的Json:
[1,{"a":2},\r\n{"a":{}}, {"a":[]},{"a":[{}]},{"{[a":"\"2,:3,"a":33}]"}]
从上面这个Json中,就可以看出需要分析的有:
1:数组和Json数组。
2:键与值(无引号、双引号)的识别
3:无限级值嵌套(数组嵌套、Json嵌套)
4:7个关键符号[{,:"}]。
5:转义符号、空格、换行、回车处理。
回顾早些年写的JsonHelper
还记得CYQ.Data里JsonHelper的最初版本,仅处理了只有一级Json的简单情况,那时候分析Json就靠以下两种方法:
1:Split 分隔。
2:循环 indexOf 识别。
虽然偷工减料,投机取巧,但只要限定使用环境和条件、好在够用,也够简单。
当然了,现在情况变了,把限定的环境和条件去除后,事实上,要分析起来就没那么简单了。
故事一开始,思考了三天三夜
由于放开了条件,需要考虑无限级递归的,于是看似Split和IndexOf这种方式已经不奏效了。
字符串的分析方法看似需要改朝换代了,但我仍给Split和IndexOf寻求最后的机会。
经过层层思考与分析,发经没折了,只有祭出终极必杀招了。
终极大招:遍历字符,记录状态
一个万能的解决方法,就是遍历每个字符,然后记录这个字符前后左右上下东南西北中发白各种状态,再根据状态来识别下一个字符的动作。
1:首先有一个记录字符状态的类,如下图:

这个字符状态的记录类,我前后不断调整了N天,才终于感觉好像OK了。
2:接下来是字符的状态设置,根据不同的关键字,设置状态,如下图:

这是个漫长不断调试的过程,很折腾人。
3:一个可以不断递归Json的函数,如下图:

4:一个可以识别语法错误的函数:

5:最后是一个给外部的调用方法:

总结:
虽然本文是关于识别Json格式,实际上,它已经是Json解析类的核心,用它可以演化出Json的各种应用,有机会再介绍了。
事实上, 一开始是原打算写Json与Xml互转那一块的,写文的意原来自最近一周折腾工作流的流程设计器那一块:

从Xml出来到前端成为Json,编辑完后回去又要转回原始格式的Xml存档,所以在Xml和Json间,必须有一套协议,这些,大概是时间不够,所以临时变了一个题目。
关于Json的在线解析,以及Json和Xml和互转,临时我开了个域名 :tool.cyqdata.com,仅方便自己使用。
夜已深,该闭眼去梦里的世界旅游了。
最后是本文的源码:
];
];
;
; i < json.Length; i++)
)
;
;
;
; i < json.Length; i++)
;
;
{
len = i + ; }
}
}
}
{
;
;
;
{
|| valueStart > )
{
}
{
isError = jsonStart && state == ; isError = !jsonStart || (keyStart != && state == ); isError = arrayStart && state == ; isError = !arrayStart || jsonStart; isError = !(jsonStart || arrayStart); {
isError = (state == && keyStart == -) || (state == && valueStart == -);
}
{
isError = }
isError = !jsonStart || state == ; isError = !(jsonStart || arrayStart); {
{
isError = state == || (state == && valueStart > ); }
{
isError = keyStart == && !setDicValue;
}
}
isError = (!jsonStart && !arrayStart) || (state == && keyStart == -) || (valueStart == - && state == ); }
}
}
{
cs.CheckIsError(c);
{
&& cs.valueStart <= )
{
cs.keyStart = ;
cs.valueStart = ;
)
{
cs.childrenStart = }
{
cs.state = ;
}
cs.jsonStart = }
&& cs.valueStart < && cs.jsonStart)
{
cs.jsonStart = cs.state = ;
cs.keyStart = ;
cs.valueStart = ;
cs.setDicValue = }
{
cs.arrayStart = }
)
{
cs.childrenStart = }
&& cs.valueStart <= ) {
cs.keyStart = ;
cs.valueStart = ;
cs.arrayStart = }
{
) {
)
{
cs.keyStart = (c == : );
}
&& c == && c == {
{
cs.keyStart = -;
}
{
cs.escapeChar = }
}
}
&& cs.jsonStart) {
)
{
cs.valueStart = (c == : );
}
&& c == && c == {
{
cs.valueStart = -;
}
{
cs.escapeChar = }
}
}
}
&& cs.valueStart < && cs.state == )
{
)
{
cs.keyStart = -;
}
cs.state = ;
}
{
&& cs.valueStart < && cs.state == )
{
cs.state = ;
cs.keyStart = ;
cs.valueStart = ;
cs.setDicValue = }
}
)
{
cs.keyStart = ;
}
&& cs.valueStart <= ) {
}
{
{
cs.escapeChar = }
{
cs.escapeChar = }
}
{
cs.escapeChar = }
{
&& cs.state == )
{
cs.keyStart = ; }
&& cs.state == && cs.jsonStart) {
cs.valueStart = ; }
}
}
}
}
}
补充内容:
发现本文访问量比较高,以上的源码在后期又有所更新,所以放出最新源码所在的地址:
https://github.com/cyq1162/cyqdata/blob/master/Tool/JsonSplit.cs
如何识别一个字符串是否Json格式的更多相关文章
- JS实现的一个query字符串转Json格式数据的方法
输入字符串的格式是 a=1&b=2&c=3 $.par2Json = function (string, overwrite) { var obj = {}, pairs = stri ...
- 从一个复杂的json格式的String内获取某key的值
如题,如何简单的从一个复杂的String格式内获取某个key的值. 例如:从下面String下取到status的值. {"response":{"info":{ ...
- JavaScript中,JSON格式的字符串与JSON格式的对象相互转化
前言:JSON是一个独立于任何语言的数据格式,因此,严格来说,没有“JSON对象”和“JSON字符串”这个说法(然而”菜鸟教程“和”W3school“使用了“JSON对象”和“JSON字符串”这个说法 ...
- .net 字符串和JSON格式的互换
近期又做了个问卷调查,问卷调查一次性要保存一二十个题目和答案!所以嘞,博主为了偷懒,就直接把答卷内容保存成了Json格式! 好处当然是很多啦! 只需一个字段就能保存整个答卷的内容! 想想都刺激!哈哈~ ...
- js实现字符串转JSON格式
在浏览器前端实现字符串转JSON格式,有多种方法,总结如下: 方法1. js函数,eval() 语法: var obj = eval ("(" + txt + ")&qu ...
- 关于C# webapi ,接口返回字符串和json格式 ,返回值中有反斜杠
最近遇到一个比较郁闷的问题,记录一下 写了一个接口,想返回json 数据,但是返回值中总是带有反斜杠... ,下面来看原因 首先,配置 webapi的路由 App_Start 文件夹下 ,WebApi ...
- List转换成json格式字符串,json格式字符串转换成list
一.List转换成json字符串 这个比较简单,导入gson-x.x.jar, List<User> users = new ArrayList<User>(); Gson g ...
- 字符串转换json格式
前台json转字符串传递后台时 用到: data: JSON.stringify({ "zh": zhanghao, "mm": mima }), 当后台返回前 ...
- js字符串转json格式与json对象转字符串
json字符串----->json对象json对象------>json字符串 使用JSON.parse()函数 this.dataList = JSON.parse(dataList); ...
随机推荐
- PHP发送短信功能
发送短信的功能主要在于获得短信接口后,在函数中模仿用户行为,例如浏览器跳转输出短信接口的链接. 需要运用的函数为 curl_init(); curl_setopt(); curl_exec(); cu ...
- 【Java EE 学习 52】【Spring学习第四天】【Spring与JDBC】【JdbcTemplate创建的三种方式】【Spring事务管理】【事务中使用dbutils则回滚失败!!!??】
一.JDBC编程特点 静态代码+动态变量=JDBC编程. 静态代码:比如所有的数据库连接池 都实现了DataSource接口,都实现了Connection接口. 动态变量:用户名.密码.连接的数据库. ...
- Oracle数据库操作分类DDL、DML、DCL、TCL类别清单异同
DDL Data Definition Language (DDL) statements are used to define the database structure or schema. S ...
- java web系统中时间比sql server中的日期少2天的解决办法
系统环境 jdk:1.7 数据库:sql server 2008 问题描述 升级1.7之后查询出来的日期就比数据库中的少2天,降回1.6版本的jdk就正常了. 问题原因及解决办法 国内网站有很多不靠谱 ...
- ADT + JNI实例
Author: Maddock Date: 2015-07-09 本文简单记录了Android中利用jni开发程序初级教程: 步骤 1 下载安装ADT 2 配置NDK 3 新建安卓工程 4 测试jni ...
- 消息中间件MetaQ高性能原因分析-转自阿里中间件
简介 MetaQ是一款高性能的消息中间件,经过几年的发展,已经非常成熟稳定,历经多年双11的零点峰值压测,表现堪称完美. MetaQ当前最新最稳定的稳本是3.x系统,MetaQ 3.x重新设计和实现, ...
- MySQL数据库1067 问题
1.MySql1067错误解决方法 http://blog.csdn.net/mhmyqn/article/details/17043921 MySql 1045解决方法 my.ini mysq ...
- InnoDB还是MyISAM 再谈MySQL存储引擎的选择
两种类型最主要的差别就是Innodb 支持事务处理与外键和行级锁.而MyISAM不支持.所以MyISAM往往就容易被人认为只适合在小项目中使用. 我作为使用MySQL的用户角度出发,Innodb和My ...
- [NHibernate]查看NHibernate生成的SQL语句
最近接触到一个用Spring.Net结合NHIbernate的项目,第一次使用,有很多配置,数据操作一旦出问题,很难找到原因,那么如何查看NHibernate发送给数据库的SQL语句呢? 当然我们可以 ...
- node - glob模块
node的glob模块允许你使用 *等符号, 来写一个glob规则,像在shell里一样,获取匹配对应规则的文件. 这个glob工具基于javascript.它使用了 minimatch 库来进行匹配 ...