1. 程式人生 > >C#判斷一個字串是否為Json字串

C#判斷一個字串是否為Json字串

思路:

1:首先有一個記錄字元狀態的類,如下圖:

這個字元狀態的記錄類,我前後不斷調整了N天,才終於感覺好像OK了。 

2:接下來是字元的狀態設定,根據不同的關鍵字,設定狀態,如下圖:

這是個漫長不斷除錯的過程,很折騰人。

3:一個可以不斷遞迴Json的函式,如下圖:

4:一個可以識別語法錯誤的函式:

5:最後是一個給外部的呼叫方法:

程式碼:

 public static class ValidJson
    {

        /// <summary>
        /// 判斷一個字串是不是合法的json字串
        /// </summary>
        /// <param name="json"></param>
        /// <returns></returns>
        public static bool IsJson(string json)
        {
            int errIndex;
            return IsJson(json, out errIndex);
        }

        private 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>
        /// <param name="json"></param>
        /// <returns></returns>
        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;
        }

        /// <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;//長度比索引+1
                        break;
                    }
                }
            }
            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;
                    }
                    #endregion
                    break;
                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;
                    #endregion
                    break;
                case '[':
                    #region 中括號開始
                    if (!cs.jsonStart)
                    {
                        cs.arrayStart = true;
                        return true;
                    }
                    else if (cs.jsonStart && cs.state == 1)
                    {
                        cs.childrenStart = true;
                        return true;
                    }
                    #endregion
                    break;
                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;
                    }
                    #endregion
                    break;
                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;
                                }
                            }

                        }
                    }
                    #endregion
                    break;
                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);
                    #endregion
                    break;
                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;
                    }
                    #endregion
                    break;
                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;
        }

    }

相關推薦

C#判斷一個字串是否Json字串

思路: 1:首先有一個記錄字元狀態的類,如下圖: 這個字元狀態的記錄類,我前後不斷調整了N天,才終於感覺好像OK了。  2:接下來是字元的狀態設定,根據不同的關鍵字,設定狀態,如下圖: 這是個漫長不斷除錯的過程,很折騰人。 3:一個可以不斷遞迴Json的函式

C判斷字元輸入是否指定字串

**題目要求: 設定口令為“yulingxi”,請求輸入,如果錯誤迴圈輸入直至正確為止。 1,偷懶用strcmp()的做法: #define _CRT_SECURE_NO_WARNINGS

C#判斷一個string是否數字(正則表示式)

方案一:Try...Catch(執行效率不高) private bool IsNumberic(string oText) {           try     &nb

C# 判斷一個時間點是否位於給定的時間區間(字串格式)

本文中實現了函式 static bool isLegalTime(DateTime dt, string time_intervals); 給定一個字5E7��串表示的時間區間time_intervals: 1)每個時間點用六位數字表示:如12點34分56秒為123456 2

java 判斷字串是否json格式

public static boolean isJson(String content) {         try {             JS

C#判斷字串是否數字字串

在進行C#程式設計時候,有的時候我們需要判斷一個字串是否是數字字串,我們可以通過以下兩種方法來實現。  【方法一】:使用 try{} catch{} 語句。        我們可以在try語句塊中試圖將string型別的字串變數轉換為int型別,如果該字串不是數字字串則會丟擲異常,這時在catch語句

PHP 判斷字串是否 Json 格式

哎,現在的網上瞎 J8 扯的人真是太多了,全 TM 一片抄! 網上一堆人說的 json_last_error(),可以判斷 json_decode 後的結果 我也沒多想,試了一下: json_dec

判斷字串是否json

function isJSON(str) {    if (typeof str == 'string') {        try {            var obj=JSON.parse(str);            if(typeof obj == 'obje

js中判斷字串是否json

function isJson(str){ if(typeof str == 'string'){ try{ var obj = JSON.parse(data); if(typeof obj == 'object' &&am

C++ 使用jsoncpp 封裝及解析 json字串(包含複雜陣列)

#include <json/json.h> #include <string> #include <iostream> using namespace std; int main() { //std::string strValue = "{\"na

json.loads()將字串轉換json格式出錯

今天爬取今日頭條的街拍時,需要將裡面的一個字串變為json格式,結果直接轉換就出現了 json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)

js 將json字串轉換json物件的方法解析(簡單處理JSON語法格式校驗問題)

js 將json字串轉換為json物件的方法解析 將json字串轉換為json物件的方法。在資料傳輸過程中,json是以文字,即字串的形式傳遞的,而JS操作的是JSON物件,所以,JSON物件和JSON字串之間的相互轉換是關鍵 例如: JSON字串: var str1 = ‘{

jquery將form表單內容轉換json字串

  var formObject = {}; var formArray = $("#form").serializeArray(); $.each(formArray, function (i, item) { formObject[item.name] = item.val

在SSH框架中,多個持久層物件相互引用,從而引發分頁查詢中,查詢所得的持久化物件轉換JSON字串報錯的原因及解決方案

引言: 使用EasyUI框架的小夥伴們都知道,在使用datagrid(資料表格)時,會傳入如一個URL,用於請求資料表格中的所顯示的資料: <!--建立一個空表格--> <table id="mytable"></table>

字串轉換JSON物件,資料精度丟失

字串轉換為JSON物件,資料精度丟失 今天在專案開發中發現了資料提交後臺處理後,精度改變問題。在一陣除錯後,發現是JSON轉換出了問題。需求是匯入一個excel表格,然後顯示內容,最後存到資料庫中。讀入表格時內容顯示:![正確資料](https://img-blog.csdn.net/20

黑馬程式設計師-判斷字串是否對稱字串

------Java培訓、Android培訓、iOS培訓、.Net培訓、期待與您交流! ------- 學習Java到現在才經歷了一個多月的時間,但是每當遇到一道題目,併成功解決的時候,都是我最開心的時候,這就是成功的喜悅感吧。  下面舉例黑馬的入學基礎測試的一些題目,和

C和Java判斷一個數字是否素數

C: /* 素數: 素數又稱質數。所謂素數是指除了 1 和它本身以外,不能被任何整數整除的數,例如17就是素數,因為它不能被 2~16 的任一整數整除。 */ # include <stdio.h> bool PrimeNumber(int val); int ma

java將list物件轉換json字串資料顯示空的資訊

1、首先是一個main 方法 public static void main(String[] args){ List l=new ArrayList(); ImageInfo a=

基於硬體的CC++)語言程式設計教程9:判斷一個年份是否閏年

本系列文章希望探討以硬體為平臺講述C(C++)知識的一個新的途徑,改變目前大多數C語言教程僅注重C語言本身的語法規則,而脫離其應用環境的現狀。希望讀者通過本教程的學習,能夠立刻學以致用,真正將所學知識應用到專案實踐中。 開發環境:Atmel Studio 7.0 硬體平臺

python:linux下字串轉換JSON

JSON是一種輕量級的資料交換格式,易於人類閱讀和編寫,同時也易於機器解析和生成。由於JSON的諸多優點,已經廣泛使用在各個系統中,因此,我們經常會有將JSON字串轉換為JSON物件的需求。 例如,在筆者的工作過程中,我們的系統會呼叫底層服務的API,底層服務的API一般都是以JSON的格式返回,為