파이썬에서 문자열이 유효한 JSON인지 어떻게 확인합니까?


184

파이썬에서는 문자열을 구문 분석하기 전에 문자열이 유효한 JSON인지 확인하는 방법이 있습니까?

예를 들어 Facebook Graph API와 같은 작업을 수행하면 때로는 JSON을 반환하고 때로는 이미지 파일을 반환 할 수도 있습니다.


3
api는 콘텐츠 유형을 설정해야합니다
John La Rooy

4
API 호출에서 반환되는 데이터를 지정할 수 없습니까? Facebook API에 익숙하지 않지만 정말 이상하게 들립니다.
jhocking

나는 한 번 수행, 한 codegolf 방법
당신

1
대부분의 답변은 json이지만 프로필 사진을 호출하면 jpg
Joey Blake

답변:


234

전달하는 문자열을 JSON으로 디코딩 할 수없는 json.loads()경우을 시도 할 수 있습니다 ValueError.

일반적으로 이런 종류의 상황에 대한 " Pythonic "철학을 EAFP 라고 하며 , 권한보다 용서를 구하기더 쉽습니다 .


4
어떻게 작동하는지 알 수 있습니다. 다음 질문으로 연결됩니다. ValueError가 발생합니다. 이 시점에서 내가 원하는 것은 문제가되는 문자열을 반환하여 다른 작업을 수행하는 것입니다. 지금까지 오류 메시지와 유형 만 얻었습니다.
Joey Blake

2
loadsexcept 절에서 전달한 문자열을 반환하면 무엇이 문제입니까 ?
John Flatness

1
내 잘못은 멍청한 실수 야 file.read ()를 두 번 호출 할 수없는 것 같습니다. 그러나 변수를 설정하고 사용할 수 있습니다. 그리고 내가 한 일입니다.
Joey Blake

5
그냥 참고 ... json.loads ('10 ')는 ValueError를 던지지 않으며'10 '은 유효한 json이 아니라고 확신합니다 ...
wahrheit

4
사양에 따르면 JSON 텍스트는 배열 또는 객체 여야한다고 말하지만 대부분의 인코더 및 디코더 (Python 포함)는 숫자와 문자열을 포함하여 "상단"에있는 모든 JSON 값과 함께 작동합니다. 10유효한 JSON 숫자 값입니다.
John Flatness

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]

파이썬 객체를 JSON 문자열로 변환하십시오.

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

저수준 파싱에 액세스하려면 직접 굴리지 말고 기존 라이브러리를 사용하십시오. 하십시오 http://www.json.org/

파이썬 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 구문 검사, 구문 분석, prittifying, 인코딩, 디코딩 등의 기능을 수행 할 수 있습니다.

https://metacpan.org/pod/json_xs


del json_object한 번 검증 해야한다고 생각하십니까 ?
Akshay

4
왜 적절한 검증 방법이 없는가? 카나리아를 죽이지 않고 오류를 확인하는 방법이 있어야합니다.
Braden Best

내가 얻는 것은 : 파이썬이 OO를 허용한다고해서 다른 부분을 무시해도 괜찮다는 것을 의미하지는 않습니다. A. 함수 실패 및 예외 사용 (OO / Python 방식) 또는 B. 예외를 throw하는 대신 값 (성공 또는 오류)을 반환하는 함수 호출 후 내 함수를 갖는 옵션이 있어야합니다. 그런 다음 오류를 나타내는 센티넬 값을 반환하여 오류가 호출 스택을 버블 링하고 필요에 따라 사용할 수 있도록합니다 (절차 / C 방식). C ++에서 예외를 사용하도록 강요하지 않는 것처럼 (errno를 사용할 수 있음), 파이썬도 강제로 강요해서는 안됩니다
Braden Best

@BradenBest JSON 문자열 유효성 검사는 중지 문제를 흥미롭게 만드는 악마에 의해 무시됩니다. 파서를 사용하여 문자열을 시도하고 오류없이 끝나는 지 확인하는 것 외에는 문자열의 정확성을 입증하는 수학적으로 올바른 방법이 없습니다. 어려운 이유를 보려면 : "컴퓨터 프로그램에 구문 오류가 없음을 증명하는 프로그램을 작성하십시오". 그건 불가능하다. 언어 개발자는 인코딩과 디코딩의 영원한 무기 경쟁에 대해 시적인 정보를 얻습니다. 우리가 할 수있는 최선의 방법은 문자열이 주어진 엔진에 유효하고 가능한 모든 엔진에 대해 유효하지 않은 경우 예 / 아니오를 반환하는 것입니다.
Eric Leschinski

1
@EricLeschinski 그러나 여기서 멈추는 문제는 없습니다. JSON 구문 분석 중에 오류가 발생하면 프로그램에서 예외가 명확하게 발생합니다. 따라서 프로그램은 JSON 입력이 유효하지 않은시기를 알고 있습니다. 따라서을 사용할 필요없이 입력이 유효한지 확인하는 기능을 100 % 사용할 수 있습니다 try. #StopCanaryAbuse
Braden Best 1

2

파싱은 실제로 전적으로 말할 수있는 유일한 방법이라고 말할 것입니다. json.loads()올바른 형식이 아닌 경우 파이썬 기능에 의해 예외가 발생 합니다 (거의 확실합니다). 그러나 예제의 목적은 아마도 공백이 아닌 첫 문자 몇 개만 확인할 수 있습니다.

페이스 북이 다시 보내는 JSON에 익숙하지 않지만 웹 앱의 대부분의 JSON 문자열은 열린 사각형 [또는 중괄호로 시작 {합니다. 해당 문자로 시작하는 이미지 형식이 없습니다.

반대로 어떤 이미지 형식이 표시 될 수 있는지 알고있는 경우 문자열의 서명에서 서명을 확인하여 이미지를 식별하고 이미지가 아닌 경우 JSON이 있다고 가정 할 수 있습니다.

텍스트 문자열이 아닌 그래픽을 식별하는 또 다른 간단한 해킹은 그래픽을 찾고있는 경우 문자열의 첫 두 자릿수에서 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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.