如何识别一个字符串是否Json格式

这篇博客探讨了如何识别一个字符串是否符合Json格式。作者指出,网上常见的解决方案并不靠谱,并分享了自己的深入研究和挑战,包括分析Json的复杂情况,如无限级嵌套和特殊字符处理。通过遍历字符并记录状态,作者实现了一个有效的Json识别方法,这为Json解析奠定了基础。
摘要由CSDN通过智能技术生成
前言:

距离上一篇文章,又过去一个多月了,近些时间,工作依旧很忙碌,除了管理方面的事,代码方面主要折腾三个事:

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,仅方便自己使用。

 

夜已深,该闭眼去梦里的世界旅游了。 

最后是本文的源码:

  1  using System;
  2  using System.Collections.Generic;
  3  using System.Text;
  4 
  5  namespace CYQ.Data.Tool
  6 {
  7      ///   <summary>
  8       ///  分隔Json字符串为字典集合。
  9       ///   </summary>
 10       internal  class JsonSplit
 11     {
 12          private  static  bool IsJsonStart( ref  string json)
 13         {
 14              if (! string.IsNullOrEmpty(json))
 15             {
 16                 json = json.Trim( ' \r '' \n ''   ');
 17                  if (json.Length >  1)
 18                 {
 19                      char s = json[ 0];
 20                      char e = json[json.Length -  1];
 21                      return (s ==  ' { ' && e ==  ' } ') || (s ==  ' [ ' && e ==  ' ] ');
 22                 }
 23             }
 24              return  false;
 25         }
 26          internal  static  bool IsJson( string json)
 27         {
 28              int errIndex;
 29              return IsJson(json,  out errIndex);
 30         }
 31          internal  static  bool IsJson( string json,  out  int errIndex)
 32         {
 33             errIndex =  0;
 34              if (IsJsonStart( ref json))
 35             {
 36                 CharState cs =  new CharState();
 37                  char c;
 38                  for ( int i =  0; i < json.Length; i++)
 39                 {
 40                     c = json[i];
 41                      if (SetCharState(c,  ref cs) && cs.childrenStart) // 设置关键符号状态。
 42                      {
 43                          string item = json.Substring(i);
 44                          int err;
 45                          int length = GetValueLength(item,  trueout err);
 46                         cs.childrenStart =  false;
 47                          if (err >  0)
 48                         {
 49                             errIndex = i + err;
 50                              return  false;
 51                         }
 52                         i = i + length -  1;
 53                     }
 54                      if (cs.isError)
 55                     {
 56                         errIndex = i;
 57                          return  false;
 58                     }
 59                 }
 60 
 61                  return !cs.arrayStart && !cs.jsonStart;
 62             }
 63              return  false;
 64         }
 65        
 66          ///   <summary>
 67           ///  获取值的长度(当Json值嵌套以"{"或"["开头时)
 68           ///   </summary>
 69           private  static  int GetValueLength( stri
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值