Làm cách nào để kiểm tra xem một chuỗi có phải là JSON hợp lệ trong Python không?


184

Trong Python, có cách nào để kiểm tra xem một chuỗi có phải là JSON hợp lệ hay không trước khi thử phân tích chuỗi?

Ví dụ: làm việc với những thứ như API đồ thị của Facebook, đôi khi nó trả về JSON, đôi khi nó có thể trả về một tệp hình ảnh.


3
api nên đặt loại nội dung
John La Rooy

4
Bạn không thể chỉ định dữ liệu nào được trả về trong lệnh gọi API? Tôi không quen với API Facebook nhưng điều đó nghe có vẻ kỳ quặc.
jhocking

Tôi đã thực hiện một lần, nhưng với codegolf cách
BẠN

1
Hầu hết các phản hồi là json, nhưng, nếu bạn gọi ảnh hồ sơ, nó sẽ trả về jpg
Joey Blake

Câu trả lời:


235

Bạn có thể thử làm json.loads(), điều này sẽ ném ValueErrornếu chuỗi bạn vượt qua không thể được giải mã thành JSON.

Nói chung, triết lý " Pythonic " cho loại tình huống này được gọi là EAFP , vì dễ xin tha thứ hơn là cho phép .


4
Tôi có thể thấy nó sẽ hoạt động như thế nào. Dẫn tôi đến câu hỏi tiếp theo của tôi. Nó ném một ValueError. Điều tôi muốn nó làm vào thời điểm này là trả về chuỗi vi phạm để tôi có thể làm gì đó với nó. Cho đến nay, tôi chỉ nhận được thông báo lỗi và loại.
Joey Blake

2
Có gì sai khi chỉ trả về chuỗi bạn đã chuyển đến loadstrong mệnh đề ngoại trừ?
John Flatness

1
Không có gì sai với nó, chỉ là một lỗi noob về phía tôi. Có vẻ như tôi không thể gọi file.read () hai lần. Nhưng tôi có thể đặt một biến và sử dụng nó. Và đó là những gì tôi đã làm.
Joey Blake

5
chỉ là một ghi chú ... json.loads ('10 ') không ném ValueError và tôi chắc chắn' 10 'không phải là một json hợp lệ ...
wahrheit

4
Mặc dù thông số kỹ thuật nói rằng văn bản JSON phải là một mảng hoặc đối tượng, hầu hết các bộ mã hóa và giải mã (bao gồm cả Python) sẽ hoạt động với bất kỳ giá trị JSON nào ở "trên cùng", bao gồm cả số và chuỗi. 10là một giá trị số JSON hợp lệ.
John Flatness

145

Ví dụ tập lệnh Python trả về boolean nếu một chuỗi hợp lệ json:

import json

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

Bản in nào:

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

Chuyển đổi một chuỗi JSON thành một từ điển Python:

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

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

Chuyển đổi một đối tượng python thành chuỗi JSON:

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

Nếu bạn muốn truy cập vào phân tích cú pháp cấp thấp, đừng tự cuộn, hãy sử dụng thư viện hiện có: http://www.json.org/

Hướng dẫn tuyệt vời về mô-đun JSON của python: https://pymotw.com/2/json/

Là chuỗi JSON và hiển thị lỗi cú pháp và thông báo lỗi:

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

Bản in:

, 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 có khả năng kiểm tra cú pháp, phân tích cú pháp, phân tích, mã hóa, giải mã và hơn thế nữa:

https://metacpan.org/pod/json_xs


Bạn có nghĩ rằng chúng ta nên del json_objectxác nhận một lần?
Akshay

4
Tại sao địa ngục không có một phương pháp xác nhận hợp lệ? Cần có một cách để kiểm tra lỗi mà không giết chết chim hoàng yến.
Braden hay nhất

Những gì tôi nhận được là: Chỉ vì Python cho phép OO không có nghĩa là bỏ qua các phần khác. Tôi nên có tùy chọn A. để chức năng thất bại và sử dụng ngoại lệ (cách OO / Python) hoặc B. gọi một hàm trả về giá trị (thành công hoặc lỗi) thay vì ném ngoại lệ, sau đó có chức năng của tôi lần lượt, trả về giá trị sentinel chỉ ra lỗi, để lỗi xuất hiện ngăn xếp cuộc gọi và có thể được sử dụng khi cần thiết (cách thủ tục / C). Giống như C ++ không bắt buộc bạn sử dụng ngoại lệ (bạn có thể sử dụng errno), Python cũng không nên ép buộc
Braden Best

Xác thực chuỗi JSON @BradenBest bị ám bởi con quỷ khiến vấn đề tạm dừng trở nên thú vị. Không có cách chính xác nào về mặt toán học để chứng minh tính đúng đắn của chuỗi ngoại trừ thử chuỗi của bạn với trình phân tích cú pháp và xem nếu nó kết thúc mà không có lỗi. Để biết lý do tại sao nó khó: "Viết cho tôi một chương trình chứng minh không có lỗi cú pháp tồn tại trong chương trình máy tính". Đó là không thể. Các nhà phát triển ngôn ngữ sẽ thơ mộng về cuộc chạy đua vũ trang mã hóa và giải mã vĩnh cửu. Điều tốt nhất chúng ta có thể làm là trả về có / không nếu một chuỗi hợp lệ cho một công cụ nhất định, không phải cho tất cả các công cụ có thể.
Eric Leschinski

1
@EricLeschinski nhưng không có vấn đề tạm dừng ở đây. Chương trình rõ ràng đưa ra một ngoại lệ nếu xảy ra lỗi trong khi phân tích cú pháp JSON. Do đó, chương trình biết khi nào đầu vào JSON không hợp lệ. Do đó, có thể có 100% chức năng kiểm tra xem đầu vào có hợp lệ mà không phải sử dụng hay không try. #StopCanaryAduse
Braden hay nhất

2

Tôi muốn nói rằng phân tích cú pháp đó là cách duy nhất bạn thực sự có thể hoàn toàn nói. Ngoại lệ sẽ được nâng lên bởi json.loads()chức năng của python (gần như chắc chắn) nếu không đúng định dạng. Tuy nhiên, mục đích của ví dụ của bạn có lẽ bạn chỉ cần kiểm tra một vài ký tự không phải khoảng trắng đầu tiên ...

Tôi không quen với JSON mà facebook gửi lại, nhưng hầu hết các chuỗi JSON từ các ứng dụng web sẽ bắt đầu bằng dấu ngoặc vuông [hoặc mở {. Không có định dạng hình ảnh tôi biết bắt đầu với những nhân vật.

Ngược lại nếu bạn biết định dạng hình ảnh nào có thể hiển thị, bạn có thể kiểm tra bắt đầu chuỗi ký tự của chúng để xác định hình ảnh và giả sử bạn có JSON nếu đó không phải là hình ảnh.

Một cách hack đơn giản khác để xác định đồ họa, thay vì chuỗi văn bản, trong trường hợp bạn đang tìm đồ họa, chỉ để kiểm tra các ký tự không phải ASCII trong vài chục ký tự đầu tiên của chuỗi (giả sử JSON là ASCII ).


0

Tôi đã đưa ra một giải pháp chung chung, thú vị cho vấn đề này:

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

và bạn có thể sử dụng nó như vậy:

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

1
Tôi nghĩ rằng các giải pháp chung là tốt, nhưng trong trường hợp này, exceptđiều khoản có thể ẩn bất kỳ ngoại lệ nghiêm trọng nào. Bắt ngoại lệ phải càng hạn chế càng tốt.
lucastamoios
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.