MainWindow.xaml.cs

    /// <summary>/// MainWindow.xaml 的交互逻辑/// </summary>public partial class MainWindow : Window{public MainWindow(){InitializeComponent();}private void btnCheckJson_Click(object sender, EventArgs e){string filepath = null;OpenFileDialog dialog = new OpenFileDialog();if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK){filepath = dialog.FileName;}if (filepath != null){string json = File.OpenText(filepath).ReadToEnd();if (JsonSplit.IsJson(json))//传入的json串
                {MessageBox.Show("json格式合法");}else{MessageBox.Show("json格式不合法");}}}}

检测json串是否合法的辅助类

    internal class JsonSplit{private static bool IsJsonStart(ref string json){if (!string.IsNullOrEmpty(json)){json = json.Trim('\r', '\n', ' ');if (json.Length > 1){char s = json[0];char e = json[json.Length - 1];return (s == '{' && e == '}') || (s == '[' && e == ']');}}return false;}internal static bool IsJson(string json){int errIndex;return IsJson(json, out errIndex);}internal static bool IsJson(string json, out int errIndex){errIndex = 0;if (IsJsonStart(ref json)){CharState cs = new CharState();char c;for (int i = 0; i < json.Length; i++){c = json[i];if (SetCharState(c, ref cs) && cs.childrenStart)//设置关键符号状态。
                    {string item = json.Substring(i);int err;int length = GetValueLength(item, true, out err);cs.childrenStart = false;if (err > 0){errIndex = i + err;return false;}i = i + length - 1;}if (cs.isError){errIndex = i;return false;}}return !cs.arrayStart && !cs.jsonStart;}return false;}/// <summary>/// 获取值的长度(当Json值嵌套以"{"或"["开头时)/// </summary>private static int GetValueLength(string json, bool breakOnErr, out int errIndex){errIndex = 0;int len = 0;if (!string.IsNullOrEmpty(json)){CharState cs = new CharState();char c;for (int i = 0; i < json.Length; i++){c = json[i];if (!SetCharState(c, ref cs))//设置关键符号状态。
                    {if (!cs.jsonStart && !cs.arrayStart)//json结束,又不是数组,则退出。
                        {break;}}else if (cs.childrenStart)//正常字符,值状态下。
                    {int length = GetValueLength(json.Substring(i), breakOnErr, out errIndex);//递归子值,返回一个长度。。。cs.childrenStart = false;cs.valueStart = 0;//cs.state = 0;i = i + length - 1;}if (breakOnErr && cs.isError){errIndex = i;return i;}if (!cs.jsonStart && !cs.arrayStart)//记录当前结束位置。
                    {len = i + 1;//长度比索引+1break;}}}return len;}/// <summary>/// 字符状态/// </summary>private class CharState{internal bool jsonStart = false;//以 "{"开始了...internal bool setDicValue = false;// 可以设置字典值了。internal bool escapeChar = false;//以"\"转义符号开始了/// <summary>/// 数组开始【仅第一开头才算】,值嵌套的以【childrenStart】来标识。/// </summary>internal bool arrayStart = false;//以"[" 符号开始了internal bool childrenStart = false;//子级嵌套开始了。/// <summary>/// 【0 初始状态,或 遇到“,”逗号】;【1 遇到“:”冒号】/// </summary>internal int state = 0;/// <summary>/// 【-1 取值结束】【0 未开始】【1 无引号开始】【2 单引号开始】【3 双引号开始】/// </summary>internal int keyStart = 0;/// <summary>/// 【-1 取值结束】【0 未开始】【1 无引号开始】【2 单引号开始】【3 双引号开始】/// </summary>internal int valueStart = 0;internal bool isError = false;//是否语法错误。internal void CheckIsError(char c)//只当成一级处理(因为GetLength会递归到每一个子项处理)
            {if (keyStart > 1 || valueStart > 1){return;}//示例 ["aa",{"bbbb":123,"fff","ddd"}] switch (c){case '{'://[{ "[{A}]":[{"[{B}]":3,"m":"C"}]}]isError = jsonStart && state == 0;//重复开始错误 同时不是值处理。break;case '}':isError = !jsonStart || (keyStart != 0 && state == 0);//重复结束错误 或者 提前结束{"aa"}。正常的有{}break;case '[':isError = arrayStart && state == 0;//重复开始错误break;case ']':isError = !arrayStart || jsonStart;//重复开始错误 或者 Json 未结束break;case '"':case '\'':isError = !(jsonStart || arrayStart); //json 或数组开始。if (!isError){//重复开始 [""",{"" "}]isError = (state == 0 && keyStart == -1) || (state == 1 && valueStart == -1);}if (!isError && arrayStart && !jsonStart && c == '\'')//['aa',{}]
                        {isError = true;}break;case ':':isError = !jsonStart || state == 1;//重复出现。break;case ',':isError = !(jsonStart || arrayStart); //json 或数组开始。if (!isError){if (jsonStart){isError = state == 0 || (state == 1 && valueStart > 1);//重复出现。
                            }else if (arrayStart)//["aa,] [,]  [{},{}]
                            {isError = keyStart == 0 && !setDicValue;}}break;case ' ':case '\r':case '\n'://[ "a",\r\n{} ]case '\0':case '\t':break;default: //值开头。。isError = (!jsonStart && !arrayStart) || (state == 0 && keyStart == -1) || (valueStart == -1 && state == 1);//
                        break;}//if (isError)//{//}
            }}/// <summary>/// 设置字符状态(返回true则为关键词,返回false则当为普通字符处理)/// </summary>private static bool SetCharState(char c, ref CharState cs){cs.CheckIsError(c);switch (c){case '{'://[{ "[{A}]":[{"[{B}]":3,"m":"C"}]}]#region 大括号if (cs.keyStart <= 0 && cs.valueStart <= 0){cs.keyStart = 0;cs.valueStart = 0;if (cs.jsonStart && cs.state == 1){cs.childrenStart = true;}else{cs.state = 0;}cs.jsonStart = true;//开始。return true;}#endregionbreak;case '}':#region 大括号结束if (cs.keyStart <= 0 && cs.valueStart < 2 && cs.jsonStart){cs.jsonStart = false;//正常结束。cs.state = 0;cs.keyStart = 0;cs.valueStart = 0;cs.setDicValue = true;return true;}// cs.isError = !cs.jsonStart && cs.state == 0;#endregionbreak;case '[':#region 中括号开始if (!cs.jsonStart){cs.arrayStart = true;return true;}else if (cs.jsonStart && cs.state == 1){cs.childrenStart = true;return true;}#endregionbreak;case ']':#region 中括号结束if (cs.arrayStart && !cs.jsonStart && cs.keyStart <= 2 && cs.valueStart <= 0)//[{},333]//这样结束。
                    {cs.keyStart = 0;cs.valueStart = 0;cs.arrayStart = false;return true;}#endregionbreak;case '"':case '\'':#region 引号if (cs.jsonStart || cs.arrayStart){if (cs.state == 0)//key阶段,有可能是数组["aa",{}]
                        {if (cs.keyStart <= 0){cs.keyStart = (c == '"' ? 3 : 2);return true;}else if ((cs.keyStart == 2 && c == '\'') || (cs.keyStart == 3 && c == '"')){if (!cs.escapeChar){cs.keyStart = -1;return true;}else{cs.escapeChar = false;}}}else if (cs.state == 1 && cs.jsonStart)//值阶段必须是Json开始了。
                        {if (cs.valueStart <= 0){cs.valueStart = (c == '"' ? 3 : 2);return true;}else if ((cs.valueStart == 2 && c == '\'') || (cs.valueStart == 3 && c == '"')){if (!cs.escapeChar){cs.valueStart = -1;return true;}else{cs.escapeChar = false;}}}}#endregionbreak;case ':':#region 冒号if (cs.jsonStart && cs.keyStart < 2 && cs.valueStart < 2 && cs.state == 0){if (cs.keyStart == 1){cs.keyStart = -1;}cs.state = 1;return true;}// cs.isError = !cs.jsonStart || (cs.keyStart < 2 && cs.valueStart < 2 && cs.state == 1);#endregionbreak;case ',':#region 逗号 //["aa",{aa:12,}]if (cs.jsonStart){if (cs.keyStart < 2 && cs.valueStart < 2 && cs.state == 1){cs.state = 0;cs.keyStart = 0;cs.valueStart = 0;//if (cs.valueStart == 1)//{//    cs.valueStart = 0;//}cs.setDicValue = true;return true;}}else if (cs.arrayStart && cs.keyStart <= 2){cs.keyStart = 0;//if (cs.keyStart == 1)//{//    cs.keyStart = -1;//}return true;}#endregionbreak;case ' ':case '\r':case '\n'://[ "a",\r\n{} ]case '\0':case '\t':if (cs.keyStart <= 0 && cs.valueStart <= 0) //cs.jsonStart &&
                    {return true;//跳过空格。
                    }break;default: //值开头。。if (c == '\\') //转义符号
                    {if (cs.escapeChar){cs.escapeChar = false;}else{cs.escapeChar = true;return true;}}else{cs.escapeChar = false;}if (cs.jsonStart || cs.arrayStart) // Json 或数组开始了。
                    {if (cs.keyStart <= 0 && cs.state == 0){cs.keyStart = 1;//无引号的
                        }else if (cs.valueStart <= 0 && cs.state == 1 && cs.jsonStart)//只有Json开始才有值。
                        {cs.valueStart = 1;//无引号的
                        }}break;}return false;}}

转载于:https://www.cnblogs.com/ouyangqiao/p/5642592.html

C#检查json格式是否合法相关推荐

  1. C语言json格式校验

    C语言json格式校验 最近用到json格式数据传输信息,在C语言中使用cjson解析json字符串,若json格式不正确,会使整个进程直接挂掉.想到能否在解析前先进行格式校验,通过后再解析,查找资料 ...

  2. 导入数据任务(id:373985)异常, 错误信息:解析导入文件错误,请检查导入文件内容,仅支持导入json格式数据及excel文件

    导入数据任务(id:373985)异常, 错误信息:解析导入文件错误,请检查导入文件内容,仅支持导入json格式数据及excel文件 参考文章: (1)导入数据任务(id:373985)异常, 错误信 ...

  3. 导入数据任务(id:373985)异常, 错误信息:解析导入文件错误,请检查导入文件内容,仅支持导入json格式数据及excel文件...

    小程序导入,别人导出的数据库json文件,错误信息如下: 导入数据库失败, Error: Poll error, 导入数据任务(id:373985)异常,错误信息:解析导入文件错误,请检查导入文件内容 ...

  4. js前台提示:参数不规范,请检查json的格式和参数对应的类型是否正确

    如图: 原来的代码是这样的: 这样的:(相当于导入另外的模块,其中validate.rule.extend.jsp里面存放了对应的提示语) 上面代码限定了文本框里面只能输入1000以内的数字,但是当输 ...

  5. 一次渗透测试引发Json格式下的CSRF攻击

    0x00 前言 漏洞背景 hw时期在电信三巨头之一旗下的子公司出差,做一下渗透测试.公网的业务主挖逻辑漏洞,但是每次挖着挖着就变成了CSRF攻击,出差半个月算是把这辈子的CSRF都给挖完了. test ...

  6. java json数据输出,java服务器端输出JSON格式数据

    java服务器端输出JSON格式数据 本文我们讨论如何在服务器端输出 JSON 格式的数据.以 Java 为例,我们将演示将一个 Java 对象编码为 JSON 格式的文本. 将 String 对象编 ...

  7. 数据库中省区市组装成json_全国各省、市、县、镇、村的mysql数据库和JSON格式数据...

    ------------------ 直接开门见山了,放出下载地址先: phpmyadmin压缩导出的mysql库,库名:ajing,内有6个表,一个表不带后缀的是原始数据,每一行是一个村,从省至村: ...

  8. json格式的字符串转为json对象遇到特殊字符问题解决

    中午做后台发过来的json的时候转为对象,可是有几条数据一直出不来,检查发现json里包含了换行符,造成这种情况的原因可能是编辑部门在编辑的时候打的回车造成的 假设有这样一段json格式的字符串 1 ...

  9. python操作json_Python学习之利用Python处理JSON格式数据

    最近在研究利用zabbix的自动发现功能来监控一台服务器上的多个Redis端口.网上有篇文章写个Python程序来发现Redis端口并显示成JSON格式.这里就学习下Python如何处理JSON格式数 ...

最新文章

  1. 建模的常用手段:组合与聚合
  2. poj3580 伸展树(区间翻转 区间搬移 删除结点 加入结点 成段更新)
  3. 使用node https module创建服务器遇到的mac verify failure错误消息
  4. 解读最新的 Xamarin 更新
  5. express接受get数据
  6. python入门23 pymssql模块(python连接sql server增删改数据 )
  7. python编的俄罗斯方块游戏_python编写俄罗斯方块
  8. 募资补充粮草、成交额翻倍增长,想翻身的国美开始造势
  9. 不在gopath目录下能使用godoc吗_一文搞懂 Go Modules 前世今生及入门使用
  10. 免费JSON格式的服务接口
  11. matlab求解微积分
  12. 2019PR怎么设置导出比特率?为什么我的PR导出的时候不能控制文件大小?为什么我的PR导出的文件特别大?
  13. 关于笔记本加固态硬盘装系统的问题的解决办法
  14. 如何通过TXT文件批量生成汉信码
  15. 数据分析从零到精通第三课 python自动化和BI数据可视化实战
  16. 计算机组成原理英语翻译,计算机课程英文翻译
  17. 安装 FME Desktop 2020 教程(内置补丁可以有效激活软件)
  18. np.arange()和 range()的用法及区别
  19. stm32h743单片机嵌入式学习笔记7-FPU
  20. 计算机视觉与深度学习(4)

热门文章

  1. 【SQLAlchemy】PostgreSQL的自增长主键定义
  2. 图片压缩工具optipng/jpegoptim安装
  3. 读书笔记2013-1--暗时间(刘未鹏)
  4. Vim 的补全模式加速器,轻松玩转全部 15 种自动补全模式
  5. 配置终端服务连接的安全设置
  6. Ubuntu Tweak 0.8.2 发布
  7. html插入javascript变量,javascript如何引用变量?
  8. Nacos源码NacosAutoServiceRegistration
  9. RabbitMQ 的概念
  10. 分页和条件查询接口开发