文字列がPythonで有効なJSONかどうかを確認するにはどうすればよいですか?


184

Pythonで、文字列を解析する前に有効なJSONかどうかを確認する方法はありますか?

たとえば、Facebook Graph APIのようなものを操作する場合、JSONを返すこともあれば、画像ファイルを返すこともあります。


3
APIはコンテンツタイプを設定する必要があります
John La Rooy 2011

4
API呼び出しで返されるデータを指定できませんか?私はFacebook APIに精通していませんが、それは本当に奇妙に聞こえます。
2011

私は1度やったことがありますコードゴルフの方法で
YOU

1
ほとんどの応答はjsonですが、プロフィール写真を呼び出すと、jpgが返されます
Joey Blake

回答:


235

あなたがしようとすることができますjson.loads()、それはValueErrorあなたが渡す文字列がJSONとしてデコードできない場合にスローします。

一般的に、この種の状況に対する「Pythonic」の哲学は、許可よりも許しを求めるのが簡単なためEAFPと呼ばれています。


4
それがどのように機能するかがわかります。次の質問へと私を導きます。ValueErrorをスローします。この時点で私がしたいことは、問題のある文字列を返すことです。そうすれば、他の何かを実行できます。これまでのところ、エラーメッセージとタイプしか取得していません。
ジョーイブレイク

2
loadsexcept句で渡した文字列を単に返すことの何が問題になっていますか?
John Flatness

1
それは何も悪いことではなく、私の側のnoobの間違いです。file.read()を2回呼び出せないようです。しかし、変数を設定して使用できます。そして、それは私がやったことです。
ジョーイブレイク

5
ただのメモ... json.loads('10 ')はValueErrorをスローせず、'10'は有効なjsonではないと確信します...
wahrheit

4
仕様ではJSONテキストは配列またはオブジェクトである必要があると記載されていますが、ほとんどのエンコーダーおよびデコーダー(Pythonを含む)は、数値や文字列など、「先頭」のJSON値で動作します。10有効なJSON数値です。
John Flatness 2014

145

文字列が有効なjsonの場合、Pythonスクリプトの例ではブール値を返します。

import json

def is_json(myjson):
  try:
    json_object = json.loads(myjson)
  except ValueError as e:
    return False
  return True

どのプリント:

print is_json("{}")                          #prints True
print is_json("{asdf}")                      #prints False
print is_json('{ "age":100}')                #prints True
print is_json("{'age':100 }")                #prints False
print is_json("{\"age\":100 }")              #prints True
print is_json('{"age":100 }')                #prints True
print is_json('{"foo":[5,6.8],"foo":"bar"}') #prints True

JSON文字列をPython辞書に変換します。

import json
mydict = json.loads('{"foo":"bar"}')
print(mydict['foo'])    #prints bar

mylist = json.loads("[5,6,7]")
print(mylist)
[5, 6, 7]

PythonオブジェクトをJSON文字列に変換します。

foo = {}
foo['gummy'] = 'bear'
print(json.dumps(foo))           #prints {"gummy": "bear"}

低レベルの解析にアクセスしたい場合は、独自のロールを行わず、既存のライブラリを使用してくださいhttp : //www.json.org/

Python JSONモジュールの素晴らしいチュートリアル:https : //pymotw.com/2/json/

文字列JSONであり、構文エラーとエラーメッセージを表示します。

sudo cpan JSON::XS
echo '{"foo":[5,6.8],"foo":"bar" bar}' > myjson.json
json_xs -t none < myjson.json

プリント:

, or } expected while parsing object/hash, at character offset 28 (before "bar}
at /usr/local/bin/json_xs line 183, <STDIN> line 1.

json_xs 構文チェック、構文解析、暗号化、エンコード、デコードなどが可能です。

https://metacpan.org/pod/json_xs


del json_object一度検証する必要があると思いますか?
Akshay 2017年

4
なぜ適切な検証方法がないのですか?カナリアを殺さずにエラーチェックする方法があるはずです。
ブレーデンベスト

私が得ているのは:PythonがOOを許可しているからといって、他の部分を無視しても大丈夫という意味ではありません。A.関数を失敗させて例外を使用する(OO / Pythonの方法)、またはB.例外をスローする代わりに値を返す関数(成功またはエラー)を呼び出してから、関数を使用するオプションがあるはずですは、次に、エラーを示すセンチネル値を返します。これにより、エラーがコールスタックに浮上し、必要に応じて使用できるようになります(手続き型/ Cの方法)。C ++例外を(あなたはエラー番号を使用することができます)を使用することを強制しないのと同じように、Pythonはどちらか、それを強制すべきではない
ブレーデンベスト

@BradenBest JSON文字列検証は、停止問題を興味深いものにする悪魔に悩まされています。パーサーで文字列を試し、エラーなしで終了するかどうかを確認することを除いて、文字列が正しいことを証明する数学的に正しい方法はありません。なぜそれが難しいのかを確認するには、「コンピュータプログラムに構文エラーが存在しないことを証明するプログラムを私に書いてください」。それは可能ではありません。言語開発者は、エンコーディングとデコーディングの永遠の軍拡競争について、詩的になります。私たちができる最善のことは、文字列が特定のエンジンに対して有効である場合、すべての可能なエンジンに対してではなく、yes / noを返すことです。
Eric Leschinski、

1
@EricLeschinskiですが、ここでは停止の問題はありません。JSONの解析中にエラーが発生した場合、プログラムは明らかに例外を発生させます。したがって、プログラムは、JSON入力が無効であることを認識します。したがって、を使用せずに、入力が有効かどうかをチェックする関数を100%持つことができますtry。#StopCanaryAbuse
ブレーデンベスト

2

それを解析することがあなたが本当に完全に言うことができる唯一の方法だと私は言うでしょう。json.loads()正しい形式でない場合、Pythonの関数によって例外が発生します(ほぼ間違いなく)。ただし、例の目的では、おそらく空白以外の文字の最初の2組だけを確認できます...

私はFacebookが送り返すことをJSONに慣れていないんだけど、Webアプリケーションから最もJSON文字列は、オープン正方形の始まります[かカーリー{ブラケット。私が知っている画像フォーマットは、それらの文字で始まりません。

逆に、表示される画像フォーマットがわかっている場合は、文字列の先頭の署名をチェックして画像を識別し、画像でない場合はJSONであると想定できます。

テキスト文字列ではなくグラフィックを特定するためのもう1つの簡単なハックは、グラフィックを探している場合に、文字列の最初の数十文字の非ASCII文字をテストすることです(JSONがASCIIであると想定) )。


0

私はこの問題の一般的で興味深い解決策を思いつきました:

class SafeInvocator(object):
    def __init__(self, module):
        self._module = module

    def _safe(self, func):
        def inner(*args, **kwargs):
            try:
                return func(*args, **kwargs)
            except:
                return None

        return inner

    def __getattr__(self, item):
        obj = getattr(self.module, item)
        return self._safe(obj) if hasattr(obj, '__call__') else obj

そしてあなたはそれを次のように使うことができます:

safe_json = SafeInvocator(json)
text = "{'foo':'bar'}"
item = safe_json.loads(text)
if item:
    # do something

1
一般的な解決策は良いと思いますが、この場合、このexcept条項は重大な例外を隠す可能性があります。例外のキャッチはできるだけ制限的でなければなりません。
lucastamoios 2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.