文字列がJavaScriptで有効なJSON文字列かどうかを、Try / Catchを使用せずに確認する方法


548

何かのようなもの:

var jsonString = '{ "Id": 1, "Name": "Coke" }';

//should be true
IsJsonString(jsonString);

//should be false
IsJsonString("foo");
IsJsonString("<div>foo</div>")

ソリューションには、try / catchを含めないでください。私たちの一部は「すべてのエラーでブレーク」をオンにし、デバッガがこれらの無効なJSON文字列をブレークするのを嫌います。


25
使用しない正当な理由はありますtryか?
Nick T

7
@NickTデバッガーで「すべてのエラーで中断」をオンにすると、オンになります。Chromeには、キャッチされていないエラーを解消するオプションがあります。
Chi Chan

6
たった2行でtry catchで確認してください。var isValidJSON = true; {JSON.parse(jsonString)} catch {isValidJSON = false;を試してください。}
efkan

18
それがうまくいく間、それはひどく無骨で悪い習慣です。Try / Catchは、一般的なプログラムフローではなく、例外的な動作とエラー処理を目的としています。
Tasgall 2017年

7
@Tasgall原則として、はい。しかし、try / catchアプローチがバリデータベースのアプローチよりもパフォーマンスが高い場合はどうしますか?選択肢が「悪い習慣」であるという理由だけで(時には大幅に)遅いオプションを選択しますか?try / catchメソッドには機能的に問題はないため、使用しない理由はありません。新しいプログラマーが優れたコーディング標準を開発することは重要ですが、特にガイドラインが必要以上に困難な場合は、従来のガイドラインへのブラインド遵守を強化しないことも同様に重要です。
Abion47

回答:


172

最初にコメント。問題はを使用しないことtry/catchでした。
使用しない場合は、以下の回答をお読みください。ここではJSON、正規表現を使用して文字列を確認するだけで、ほとんどの場合に機能します。

https://github.com/douglascrockford/JSON-js/blob/master/json2.jsの 450行目をご覧ください

次のような有効なJSONをチェックする正規表現があります。

if (/^[\],:{}\s]*$/.test(text.replace(/\\["\\\/bfnrtu]/g, '@').
replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {

  //the json is ok

}else{

  //the json is not ok

}

編集:json2.jsの新しいバージョンは、上記よりも高度な解析を行いますが、正規表現の置換に基づいています(@Mrchiefコメントから)


59
これは、コードがevalを使用しても安全かどうかを確認するだけです。たとえば、次の文字列 '2011-6-27'はそのテストに合格します。
SystemicPlural

4
@SystemicPlural、そうですが、問題はtry / catchを使用しないことに関するものでした
Mic

8
JavaScriptの正規表現で文字列が有効なJSONであるかどうかをテストすることはできません。JS正規表現は、そうするために必要な拡張機能(再帰正規表現)をサポートしていないためです。上記のコードは "{"で失敗します。
Venge

2
@Mic json2.jsはその単純なチェックを使用しなくなりました(代わりに、有効なJSONを決定するために4段階の解析を使用します)。回答を修正または削除することをお勧めします。アプローチとして、「JSONをチェックするための唯一のメカニズムとしてtry / catchを使用しない」ことには何の問題もないと私は思います。
Mrchief 2016年

8
それが彼を助けるからといって、それが何年か後に同じ質問をする残りの私たちを助けるという意味ではありません。
マッケイ

916

次のようなJSONパーサーを使用しますJSON.parse

function IsJsonString(str) {
    try {
        JSON.parse(str);
    } catch (e) {
        return false;
    }
    return true;
}

7
ありがとう、でも私はチームでこれを実行しただけで、try / catchを使用しないものを望んでいます。質問は新しいタイトルとともに編集されます。申し訳ありません。
チーチャン

4
@trejder:1は文字列ではないため、「1」で試してみてください
Purefan

31
@ガンボ私のコメントは1.5歳です!:]覚えていません。2週間前に何をしていたのですか?:]いいえ、方法...:]
trejder

9
この回答の問題は、文字列がチェックアウトして解析すると、2回解析することになります。代わりに、不適切な解析ではfalseを返しますが、成功するとオブジェクトを返しませんか?
発がん性物質2016

5
@Carcigenicateあなたはそれを行うことができます。ただし、JSON.parse("false")評価もfalseになります。
ガンボ2016年

446

私はこの質問に3年遅れていることを知っていますが、私は声を上げたくなりました。

Gumboのソリューションはうまく機能しますが、例外が発生しないいくつかのケースを処理しません JSON.parse({something that isn't JSON})

また、解析されたJSONを同時に返すことを好むので、呼び出し元のコードでJSON.parse(jsonString)2回目に呼び出す必要はありません。

これは私のニーズにうまく機能するようです:

function tryParseJSON (jsonString){
    try {
        var o = JSON.parse(jsonString);

        // Handle non-exception-throwing cases:
        // Neither JSON.parse(false) or JSON.parse(1234) throw errors, hence the type-checking,
        // but... JSON.parse(null) returns null, and typeof null === "object", 
        // so we must check for that, too. Thankfully, null is falsey, so this suffices:
        if (o && typeof o === "object") {
            return o;
        }
    }
    catch (e) { }

    return false;
};

9
ページの回答のうち、これが最も堅牢で信頼性の高いものです。
Jonline 2014年

28
o && o !== null不必要です。
Aleksei Matiushkin、2014年

4
常に文字列を返すtypeofで三重等号を使用しています。:)
Hein Haraldson Berg 14

5
古いポストにもかかわらず、私は入れて、それは価値があると思ったフィドルを ..あなたは、JSON文字列を渡す必要があり、オブジェクトが有効でないことに注意してください、あなたの答えの@matthを実証アップしてください。私が推測することを始める誰にとっても役に立つかもしれません。
MindVox 2016年

2
は有効なjson文字列であり、andundefinedfalsefalsetryParseJSON("false")tryParseJSON("garbage")
スペアバイトを区別する

54
// vanillaJS
function isJSON(str) {
    try {
        return (JSON.parse(str) && !!str);
    } catch (e) {
        return false;
    }
}

使用法:に isJSON({})なりますfalse、にisJSON('{}')なりますtrue

何かがArrayor Object解析された JSON)かどうかを確認するには:

// vanillaJS
function isAO(val) {
    return val instanceof Array || val instanceof Object ? true : false;
}

// ES2015
var isAO = (val) => val instanceof Array || val instanceof Object ? true : false;

使用法:に isAO({})なりますtrue、にisAO('{}')なりますfalse


4
nullこの検証に合格するので注意してください。
Farzad YZ 2017

2
return !!(JSON.parse(str) && str);null値をブロックする必要があります。このコードで回答を更新します。
マチャド

1
これは、JSONがオブジェクト化されているかどうかも確認できるため、parse()テストに合格せず、WTFが発生するため、これが最良の答えです。
not2qubit 2018

30

ここに私の作業コード:

function IsJsonString(str) {
  try {
    var json = JSON.parse(str);
    return (typeof json === 'object');
  } catch (e) {
    return false;
  }
}

1
IsJsonString(null); // trueを返します。それを比較することで修正できますtypeof str === 'string'
gramcha

23

本当に簡単な方法を使用して、文字列が有効なJSONであるかどうかを確認しました。

function testJSON(text){
    if (typeof text!=="string"){
        return false;
    }
    try{
        JSON.parse(text);
        return true;
    }
    catch (error){
        return false;
    }
}

有効なJSON文字列を使用した結果:

var input='["foo","bar",{"foo":"bar"}]';
testJSON(input); // returns true;

単純な文字列の結果。

var input='This is not a JSON string.';
testJSON(input); // returns false;

オブジェクトの結果:

var input={};
testJSON(input); // returns false;

null入力の結果:

var input=null;
testJSON(input); // returns false;

null変数の型はオブジェクトであるため、最後の1つはfalseを返します。

これは常に機能します。:)


1
JSON.parse(null)、JSON.parse( "false")はエラーをスローしません。おそらく他にも例があります
klodoma

ええ、あなたは正しいです、私は入力が文字列かどうかを確認するのを忘れていましnullた ただし、「false」入力は有効なJSON文字列です。これはに解析されboolean (false)ます。次に、より正確になるようにコードを変更します。
kukko 2018年

15

prototypeJSには、メソッドisJSONがあります。あなたはそれを試すことができます。jsonも役立つかもしれません。

"something".isJSON();
// -> false
"\"something\"".isJSON();
// -> true
"{ foo: 42 }".isJSON();
// -> false
"{ \"foo\": 42 }".isJSON();

9
ありがとうございます。ただし、プロトタイプライブラリを使用してこれを行うのは少しやり過ぎだと思います。
Chi Chan

4
4つの例を挙げましたが、結果は3つだけでした。の結果は"{ foo: 42 }".isJSON()何ですか?もしfalse私が想定しているように(結果は機能のドキュメントに従うべきです)、良い質問は、なぜそれが間違っているのですか?{ foo: 42 }完全に有効なJSONのようです。
trejder 2012

4
@trejder残念ながら、JSON仕様では引用符付きのキーが必要です。
mikermcneil 2012年

4
また、 "2002-12-15" .isJSONはtrueを返し、JSON.parse( "2002-12-15")はエラーをスローします。
ychaouche

4
ここでのより良い答えは、その関数をプロトタイプライブラリから引き出して、ここに配置することだと思います。特にapi.prototypejs.org/language/string/prototype/isjsonは404です
。– jcollum

5

プロトタイプフレームワークのString.isJSON定義からここに

/**
   *  String#isJSON() -> Boolean
   *
   *  Check if the string is valid JSON by the use of regular expressions.
   *  This security method is called internally.
   *
   *  ##### Examples
   *
   *      "something".isJSON();
   *      // -> false
   *      "\"something\"".isJSON();
   *      // -> true
   *      "{ foo: 42 }".isJSON();
   *      // -> false
   *      "{ \"foo\": 42 }".isJSON();
   *      // -> true
  **/
  function isJSON() {
    var str = this;
    if (str.blank()) return false;
    str = str.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@');
    str = str.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']');
    str = str.replace(/(?:^|:|,)(?:\s*\[)+/g, '');
    return (/^[\],:{}\s]*$/).test(str);
  }

これは文字列オブジェクトを渡して使用できるバージョンです

function isJSON(str) {
    if ( /^\s*$/.test(str) ) return false;
    str = str.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@');
    str = str.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']');
    str = str.replace(/(?:^|:|,)(?:\s*\[)+/g, '');
    return (/^[\],:{}\s]*$/).test(str);
  }

function isJSON(str) {
    if ( /^\s*$/.test(str) ) return false;
    str = str.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@');
    str = str.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']');
    str = str.replace(/(?:^|:|,)(?:\s*\[)+/g, '');
    return (/^[\],:{}\s]*$/).test(str);
  }

console.log ("this is a json",  isJSON( "{ \"key\" : 1, \"key2@e\" : \"val\"}" ) )

console.log("this is not a json", isJSON( "{ \"key\" : 1, \"key2@e\" : pippo }" ) )


1
誰かがこれらすべての答えを比較するためのテストスイートを持っていますか?これが正しいかどうか知りたいのですが。
ロニーベスト

1
@LonnieBest良い点。私の2セント。私は何年もプロダクションで使用してきましたが、常に問題なく動作し、実行時間も妥当でした。
loretoparisi

4

この答えは、trycatchステートメントのコストを削減します。

私はJQueryを使用してJSON文字列を解析し、trycatchステートメントを使用して例外を処理しましたが、解析不可能な文字列に対して例外をスローするとコードの速度が低下したため、単純なRegexを使用して、可能性のあるJSON文字列かどうかを確認しました構文をチェックしてから、JQueryを使用して文字列を解析する通常の方法を使用しました。

if (typeof jsonData == 'string') {
    if (! /^[\[|\{](\s|.*|\w)*[\]|\}]$/.test(jsonData)) {
        return jsonData;
    }
}

try {
    jsonData = $.parseJSON(jsonData);
} catch (e) {

}

前のコードを再帰関数でラップして、ネストされたJSON応答を解析しました。


jQueryはJSON.parse()が何をしないのですか?
ADJenks

3

多分それは役に立つでしょう:

    function parseJson(code)
{
    try {
        return JSON.parse(code);
    } catch (e) {
        return code;
    }
}
function parseJsonJQ(code)
{
    try {
        return $.parseJSON(code);
    } catch (e) {
        return code;
    }
}

var str =  "{\"a\":1,\"b\":2,\"c\":3,\"d\":4,\"e\":5}";
alert(typeof parseJson(str));
alert(typeof parseJsonJQ(str));
var str_b  = "c";
alert(typeof parseJson(str_b));
alert(typeof parseJsonJQ(str_b));

出力:

IE7:文字列、オブジェクト、文字列、文字列

CHROME:オブジェクト、オブジェクト、文字列、文字列


2

なぜあなたはそれを避けたいのか私は知っていると思います。しかし、たぶんやってみてキャッチ!==やってみてキャッチ。; o)これが私の頭に浮かびました:

var json_verify = function(s){ try { JSON.parse(s); return true; } catch (e) { return false; }};

したがって、次のようにJSONオブジェクトにクリップをダーティにすることもできます。

JSON.verify = function(s){ try { JSON.parse(s); return true; } catch (e) { return false; }};

これは可能な限りカプセル化されているため、エラーが発生しても壊れない可能性があります。


2

こちらもtypescriptバージョンです:

JSONTryParse(input) {
    try {
        //check if the string exists
        if (input) {
            var o = JSON.parse(input);

            //validate the result too
            if (o && o.constructor === Object) {
                return o;
            }
        }
    }
    catch (e) {
    }

    return false;
};

Typescriptはjavascriptではありませんが、あなたの答えはそうです。
ロニーベスト

1

var jsonstring='[{"ConnectionString":"aaaaaa","Server":"ssssss"}]';

if(((x)=>{try{JSON.parse(x);return true;}catch(e){return false}})(jsonstring)){

document.write("valide json")

}else{
document.write("invalide json")
}


1

最初のコメントから、ユースケースは応答がHTMLであるかJSONであるかを示していると推測します。その場合、あなたは時に行う JSONを受け、あなたはおそらく、それを解析し、とにかくあなたのコードの中でいくつかの点で無効なJSONを扱うであるべきです。何であれ、JSONが予期されているが無効なJSONが受信された場合にブラウザーから通知を受けたいと思っていると思います(意味のあるエラーメッセージのプロキシによるユーザーの場合も同様です)。

したがって、JSONに対して完全な正規表現を実行する必要はありません(私の経験では、ほとんどのユースケースでそうです)。あなたはおそらく以下のようなものを使う方が良いでしょう:

function (someString) {
  // test string is opened with curly brace or machine bracket
  if (someString.trim().search(/^(\[|\{){1}/) > -1) {
    try { // it is, so now let's see if its valid JSON
      var myJson = JSON.parse(someString);
      // yep, we're working with valid JSON
    } catch (e) {
      // nope, we got what we thought was JSON, it isn't; let's handle it.
    }
  } else {
    // nope, we're working with non-json, no need to parse it fully
  }
}

それはあなたが例外ハンドル有効な非JSONコードを有する保存する必要があります同時に、ダフのJSONの世話をします。


このハイブリッドソリューションは、JSON以外のほとんどのケースでtry catchを実行する必要がないようにする効率的な方法のようです。私はあなたのアプローチのその側面が好きです。
ロニーベスト

1
if(resp) {
    try {
        resp = $.parseJSON(resp);
        console.log(resp);
    } catch(e) {
        alert(e);
    }
}

これもあなたのために働くことを願っています


0
function get_json(txt)
{  var data

   try     {  data = eval('('+txt+')'); }
   catch(e){  data = false;             }

   return data;
}

エラーがある場合は、falseを返します。

エラーがない場合は、jsonデータを返します


4
質問:「ソリューションにtry / catchを含めないでください」。
ddmps 2013年

1
どうして?これは保証された方法です...使用しないのはばかげています。英語が分からなくてごめんなさい。私はGoogle翻訳を使用しました
Emrah Tuncel 2013年

面白い。JSON.parseとこのevalベースのソリューションのパフォーマンス比較を見たいのですが。しかし、これはセキュリティ/インジェクションの観点からは恐ろしく見えます。
ロニーベスト

0

javascript eval()関数を使用して、それが有効かどうかを確認できます。

例えば

var jsonString = '{ "Id": 1, "Name": "Coke" }';
var json;

try {
  json = eval(jsonString);
} catch (exception) {
  //It's advisable to always catch an exception since eval() is a javascript executor...
  json = null;
}

if (json) {
  //this is json
}

または、json.orgのJSON.parse関数を使用できます。

try {
  json = JSON.parse(jsonString);
} catch (exception) {
  json = null;
}

if (json) {
  //this is json
}

お役に立てれば。

WARNINGeval()ある危険な誰かが悪意のJSコードを追加する場合、それはそれを実行するので、。JSON文字列が信頼できることを確認してください。つまり、信頼できるソースから取得したものです。

編集最初のソリューションでは、これを行うことをお勧めします。

 try {
      json = eval("{" + jsonString + "}");
    } catch (exception) {
      //It's advisable to always catch an exception since eval() is a javascript executor...
      json = null;
    }

json-ness を保証するため。jsonStringが純粋なJSONでない場合、evalは例外をスローします。


evalを使用した最初の例は、「<div> foo </ div>」が有効なJSONであることを示しています。ブラウザによって動作は異なりますが、FireFoxではeval()がXMLを受け入れるようです。
Mark Lutton、2010

ありがとう、でも私はチームでこれを実行しただけで、try / catchを使用しないものを望んでいます。質問は新しいタイトルとともに編集されます。申し訳ありません。
チーチャン

@Mark Lutton、オブジェクトタイプはJSONではなくXML Dom Documentになります(Firefoxの正確なタイプを忘れてしまいました)。
ブハケシンディ

1
evalは、「alert(5);」のような有効なJavaScriptも受け入れます。単一引用符で囲まれた文字列。これは有効なJSONではありません。
Mark Lutton、2010

12
これは純粋な評価です。
クリスベイカー

0

ああ、間違いなくtry catchを使用して、有効なJSONかどうかを確認できます

Firfox Quantom 60.0.1でテスト済み

関数内でfunctionを使用してJSONをテストし、その出力を使用して文字列を検証します。例を聞く。

    function myfunction(text){

       //function for validating json string
        function testJSON(text){
            try{
                if (typeof text!=="string"){
                    return false;
                }else{
                    JSON.parse(text);
                    return true;                            
                }
            }
            catch (error){
                return false;
            }
        }

  //content of your real function   
        if(testJSON(text)){
            console.log("json");
        }else{
            console.log("not json");
        }
    }

//use it as a normal function
        myfunction('{"name":"kasun","age":10}')

0

私の場合、IsJsonString(str)を使用している関数が機能JSON.parse(str)しません。
私はそれが常にfalseを返すGraphiQLからのjson出力を検証しようとしました。幸運なことに、isJSONはよりうまく機能します。

var test = false;

$('body').on('DOMSubtreeModified', '.resultWrap', function() {

    if (!test) {   
        var resultWrap = "{" + $('#graphiql .resultWrap').text().split("{").pop();
        if isJSON(resultWrap) {test = !test;}
        console.log(resultWrap); 
        console.log(resultWrap.isJSON());
    }

});

出力例:

THREE.WebGLRenderer 79
draw.js:170 {xxxxxxxxxx
draw.js:170 false
draw.js:170 {xxxxxxxxxx 
draw.js:170 false
draw.js:170 {xxxxxxxxxx 
draw.js:170 false
draw.js:170 {xxxxxxxxxx 
draw.js:170 false
draw.js:170 {​
draw.js:170 false
draw.js:170 {  "PI": 3.141592653589793,​
draw.js:170 false
draw.js:170 {  "PI": 3.141592653589793,  "time": 1570751209006,​
draw.js:170 false
draw.js:170 {  "PI": 3.141592653589793,  "time": 1570751209006,  "tick": 156,​
draw.js:170 false
draw.js:170 {  "PI": 3.141592653589793,  "time": 1570751209006,  "tick": 156,  "tickr": 1.56,​
draw.js:170 false
draw.js:170 {  "PI": 3.141592653589793,  "time": 1570751209006,  "tick": 156,  "tickr": 1.56,  "fps": 41.666666666666664,​
draw.js:170 false
draw.js:170 {  "PI": 3.141592653589793,  "time": 1570751209006,  "tick": 156,  "tickr": 1.56,  "fps": 41.666666666666664,  "width": 396.984,​
draw.js:170 false
draw.js:170 {  "PI": 3.141592653589793,  "time": 1570751209006,  "tick": 156,  "tickr": 1.56,  "fps": 41.666666666666664,  "width": 396.984,  "height": 327
draw.js:170 false
draw.js:170 {  "PI": 3.141592653589793,  "time": 1570751209006,  "tick": 156,  "tickr": 1.56,  "fps": 41.666666666666664,  "width": 396.984,  "height": 327}​
draw.js:170 false
draw.js:170 {  "PI": 3.141592653589793,  "time": 1570751209006,  "tick": 156,  "tickr": 1.56,  "fps": 41.666666666666664,  "width": 396.984,  "height": 327}
draw.js:170 true

0

ブール値を返し、結果を含むbyrefパラメータを処理する「try」関数の.Net規約が好きな人向け。outパラメータが必要ない場合は、省略して戻り値を使用できます。

StringTests.js

  var obj1 = {};
  var bool1 = '{"h":"happy"}'.tryParse(obj1); // false
  var obj2 = {};
  var bool2 = '2114509 GOODLUCKBUDDY 315852'.tryParse(obj2);  // false

  var obj3 = {};
  if('{"house_number":"1","road":"Mauchly","city":"Irvine","county":"Orange County","state":"California","postcode":"92618","country":"United States of America","country_code":"us"}'.tryParse(obj3))
    console.log(obj3);

StringUtils.js

String.prototype.tryParse = function(jsonObject) {
  jsonObject = jsonObject || {};
  try {
    if(!/^[\[{]/.test(this) || !/[}\]]$/.test(this)) // begin / end with [] or {}
      return false; // avoid error handling for strings that obviously aren't json
    var json = JSON.parse(this);
    if(typeof json === 'object'){
      jsonObject.merge(json);
      return true;
    }
  } catch (e) {
    return false;
  }
}

ObjectUtils.js

Object.defineProperty(Object.prototype, 'merge', {
  value: function(mergeObj){
    for (var propertyName in mergeObj) {
      if (mergeObj.hasOwnProperty(propertyName)) {
        this[propertyName] = mergeObj[propertyName];
      }      
    }
    return this;
  },
  enumerable: false, // this is actually the default
});

-2

非常にシンプルな1行のコード(ただしHackyアプローチ)

if (expected_json.id === undefined){
   // not a json
}
else{
   // json
}

注:これは、idなどのJSON文字列が必要な場合にのみ機能します。私はそれをAPIに使用しており、JSONまたは何らかのエラー文字列の結果を期待しています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.