ฉันจะตรวจสอบว่าสตริงเป็น JSON ที่ถูกต้องใน Python ได้อย่างไร


184

ใน Python มีวิธีการตรวจสอบว่าสตริงเป็น JSON ที่ถูกต้องก่อนที่จะพยายามแยกมันหรือไม่?

ตัวอย่างเช่นการทำงานกับสิ่งต่างๆเช่น Facebook Graph API บางครั้งก็ส่งคืน JSON บางครั้งอาจส่งคืนไฟล์รูปภาพ


3
API ควรตั้งค่าประเภทเนื้อหา
John La Rooy

4
คุณไม่สามารถระบุว่าข้อมูลใดที่ส่งคืนในการเรียก API ฉันไม่คุ้นเคยกับ Facebook API แต่ฟังดูแปลก ๆ
jhocking

ฉันเคยทำมาแล้วแต่ด้วยวิธีcodegolf
คุณ

1
คำตอบส่วนใหญ่คือ json แต่ถ้าคุณโทรหารูปโปรไฟล์ก็แค่ส่ง jpg กลับคืนมา
Joey Blake

คำตอบ:


234

คุณสามารถลองทำjson.loads()ซึ่งจะทำให้ValueErrorถ้าสตริงที่คุณส่งไม่สามารถถอดรหัสเป็น JSON

โดยทั่วไป " Pythonic " ปรัชญาสำหรับชนิดของสถานการณ์นี้เรียกว่าEAFPสำหรับง่ายต่อการขออนุญาตการให้อภัยกว่า


4
ฉันสามารถดูว่ามันจะทำงานอย่างไร นำฉันไปสู่คำถามต่อไป มันจะโยน ValueError สิ่งที่ฉันต้องการให้ทำในจุดนี้คือคืนสตริงที่ทำให้ขุ่นเคืองเพื่อให้ฉันสามารถทำอย่างอื่นได้ จนถึงตอนนี้ฉันได้รับข้อความแสดงข้อผิดพลาดและพิมพ์แล้วเท่านั้น
Joey Blake

2
เกิดอะไรขึ้นกับการส่งคืนสตริงที่คุณส่งไปยังloadsในข้อยกเว้น?
John Flatness

1
ไม่มีอะไรผิดปกติกับมันเพียงความผิดพลาด noob ในส่วนของฉัน ดูเหมือนว่าฉันไม่สามารถเรียกไฟล์ file.read () สองครั้ง แต่ฉันสามารถตั้งค่าตัวแปรและใช้งานได้ และนั่นคือสิ่งที่ฉันทำ
Joey Blake

5
เพียงแค่ทราบ ... json.loads ('10 ') ไม่ได้โยน ValueError และฉันแน่ใจว่า' 10 'ไม่ใช่ json ที่ถูกต้อง ...
wahrheit

4
แม้ว่าข้อเท็จจริงนั้นระบุว่าข้อความ JSON ต้องเป็นอาร์เรย์หรือวัตถุ แต่ส่วนใหญ่ตัวเข้ารหัสและถอดรหัส (รวมถึง Python) จะทำงานร่วมกับค่า JSON ใด ๆ ที่ "top" รวมถึงตัวเลขและสตริง 10เป็นค่าหมายเลข JSON ที่ถูกต้อง
John Flatness

145

ตัวอย่างสคริปต์ Python คืนค่าบูลีนหากสตริงเป็น json ที่ถูกต้อง:

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 ของ python: https://pymotw.com/2/json/

เป็น String 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 ที่ดีที่สุด

สิ่งที่ฉันได้รับคือ: เพียงเพราะ Python อนุญาตให้ OO ไม่ได้หมายความว่าจะไม่สนใจส่วนอื่น ๆ ฉันควรมีตัวเลือก A. ให้ฟังก์ชั่นล้มเหลวและใช้ข้อยกเว้น (วิธี OO / Python) หรือ B. การเรียกฟังก์ชั่นที่ส่งกลับค่า (ความสำเร็จหรือข้อผิดพลาด) แทนที่จะโยนข้อยกเว้นแล้วมีฟังก์ชั่นของฉัน ในทางกลับกันกลับค่า Sentinel ที่บ่งชี้ข้อผิดพลาดเพื่อให้ข้อผิดพลาดฟองขึ้นโทรสแต็คและสามารถใช้ตามความจำเป็น (วิธีการขั้นตอน / C) เช่นเดียวกับ C ++ ไม่บังคับให้คุณใช้ข้อยกเว้น (คุณสามารถใช้ errno), Python ไม่ควรบังคับให้มันอย่างใดอย่างหนึ่ง
Braden ดีที่สุด

การตรวจสอบความถูกต้องของสตริง @BradenBest JSON ถูกหลอกหลอนโดยอสูรที่ทำให้ปัญหาการหยุดชะงักน่าสนใจ ไม่มีวิธีที่ถูกต้องทางคณิตศาสตร์ในการพิสูจน์ความถูกต้องของสตริงยกเว้นลองใช้สตริงของคุณด้วย parser และดูว่ามันจะเสร็จสิ้นโดยไม่มีข้อผิดพลาด เพื่อดูว่าทำไมมันถึงยาก: "เขียนโปรแกรมที่ไม่มีข้อผิดพลาดทางไวยากรณ์ในโปรแกรมคอมพิวเตอร์" มันเป็นไปไม่ได้. นักพัฒนาภาษาจะแต่งบทกวีเกี่ยวกับการเข้ารหัสและถอดรหัสแขนนิรันดร์ สิ่งที่ดีที่สุดที่เราสามารถทำได้คือการคืนค่าใช่ / ไม่ใช่ถ้าสตริงนั้นใช้ได้กับเอ็นจิ้นที่กำหนดไม่ใช่สำหรับเอ็นจิ้นที่เป็นไปได้ทั้งหมด
Eric Leschinski

1
@EricLeschinski แต่ไม่มีปัญหาการหยุดพักที่นี่ โปรแกรมยกข้อยกเว้นอย่างชัดเจนหากเกิดข้อผิดพลาดขณะแยกวิเคราะห์ JSON ดังนั้นโปรแกรมจะทราบเมื่ออินพุต JSON ไม่ถูกต้อง ดังนั้นจึงเป็นไปได้ 100% tryที่จะมีฟังก์ชั่นที่การตรวจสอบว่าการป้อนข้อมูลที่ถูกต้องโดยไม่ต้องใช้ #StopCanaryAbuse
Braden ที่ดีที่สุด

2

ฉันจะบอกว่าการแยกวิเคราะห์เป็นวิธีเดียวที่คุณสามารถบอกได้อย่างแท้จริง ข้อยกเว้นจะถูกยกขึ้นโดยjson.loads()ฟังก์ชั่นของไพ ธ อน(เกือบจะแน่นอน) หากไม่ใช่รูปแบบที่ถูกต้อง อย่างไรก็ตามวัตถุประสงค์ของตัวอย่างของคุณคุณสามารถตรวจสอบอักขระที่ไม่ใช่ช่องว่างคู่แรก ...

ฉันไม่คุ้นเคยกับ JSON ที่ facebook ส่งคืน แต่สตริง 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.