How do I check if a string is valid JSON in Python?

265,824

Solution 1

You can try to do json.loads(), which will throw a ValueError if the string you pass can't be decoded as JSON.

In general, the "Pythonic" philosophy for this kind of situation is called EAFP, for Easier to Ask for Forgiveness than Permission.

Solution 2

Example Python script returns a boolean if a string is valid json:

import json

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

Which prints:

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

Convert a JSON string to a Python dictionary:

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

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

Convert a python object to JSON string:

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

If you want access to low-level parsing, don't roll your own, use an existing library: http://www.json.org/

Great tutorial on python JSON module: https://pymotw.com/2/json/

Is String JSON and show syntax errors and error messages:

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

Prints:

, 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 is capable of syntax checking, parsing, prittifying, encoding, decoding and more:

https://metacpan.org/pod/json_xs

Solution 3

I would say parsing it is the only way you can really entirely tell. Exception will be raised by python's json.loads() function (almost certainly) if not the correct format. However, the the purposes of your example you can probably just check the first couple of non-whitespace characters...

I'm not familiar with the JSON that facebook sends back, but most JSON strings from web apps will start with a open square [ or curly { bracket. No images formats I know of start with those characters.

Conversely if you know what image formats might show up, you can check the start of the string for their signatures to identify images, and assume you have JSON if it's not an image.

Another simple hack to identify a graphic, rather than a text string, in the case you're looking for a graphic, is just to test for non-ASCII characters in the first couple of dozen characters of the string (assuming the JSON is ASCII).

Share:
265,824

Related videos on Youtube

Joey Blake
Author by

Joey Blake

I like to make complicated things simple.

Updated on September 29, 2021

Comments

  • Joey Blake
    Joey Blake over 2 years

    In Python, is there a way to check if a string is valid JSON before trying to parse it?

    For example working with things like the Facebook Graph API, sometimes it returns JSON, sometimes it could return an image file.

    • John La Rooy
      John La Rooy about 13 years
      the api should set the content type
    • jhocking
      jhocking about 13 years
      You can't specify what data is returned in the API call? I'm not familiar with the Facebook API but that sounds really odd.
    • YOU
      YOU about 13 years
      I have done once, but with codegolf way
    • Joey Blake
      Joey Blake about 13 years
      Most of the responses are json, but, if you call the profile photo it just returns the jpg
  • Joey Blake
    Joey Blake about 13 years
    I can see how that will work. Leads me to my next question. It throws a ValueError. What I want it to do at this point is return the offending string so I can do something else with it. So far, I've only gotten the error message and type.
  • John Flatness
    John Flatness about 13 years
    What's wrong with just returning the string you passed to loads in the except clause?
  • Joey Blake
    Joey Blake about 13 years
    nothing wrong with it, just a noob mistake on my part. It appears I just cant call file.read() twice. But I can set a variable and use it. And thats what I did.
  • wahrheit
    wahrheit about 10 years
    just a note... json.loads('10') doesn't throw the ValueError and I'm sure '10' is not a valid json ...
  • John Flatness
    John Flatness about 10 years
    Despite the fact that the spec says that a JSON text must be an array or object, most encoders and decoders (including Python's) will work with any JSON value at the "top," including numbers and strings. 10 is a valid JSON number value.
  • Kevin
    Kevin over 9 years
    @wahrheit: If you want to detect that as an error, check whether the return value from json.loads() is a dictionary or list.
  • BomberMan
    BomberMan over 9 years
    @JohnFlatness is there anyway to check file type.. whether it is json or XML? In my case user will do input an "URL" which might consist json or xml data. so is there any way to check the type in Python?
  • KravAn
    KravAn about 8 years
    digits can be decoded as json... but than you'll have an exception when will try retrieve some parameter (TypeError: argument of type 'int' is not iterable)
  • lucastamoios
    lucastamoios over 7 years
    I think general solutions are good, but in this case, the except clause may hide any serious exception. Catching exceptions must be as restrictive as possible.
  • Akshay
    Akshay about 7 years
    Do you think we should del json_object once validated?
  • Christopher G
    Christopher G about 7 years
    EAFP :"This clean and fast style is characterized by the presence of many try and except statements." Cue this-is-fine comic.
  • Myobis
    Myobis over 6 years
    Unfortunately, {"a":1,"a":2} passes this test whereas it has duplicate property keys. Most of the parsers don't complain and usually consider the latest property .. However, there is definitely a problem.
  • John Flatness
    John Flatness over 6 years
    @Myobis the tricky bit is that the relevant standards either don't say anything at all about duplicate keys or only say that they "SHOULD" be avoided, so it's not really invalid even though it may be problematic. Python does let you get at those duplicates if you use object_pairs_hook.
  • Braden Best
    Braden Best almost 6 years
    Why the hell isn't there a proper validation method? There should be a way to error check without killing canaries.
  • Braden Best
    Braden Best almost 6 years
    What I'm getting at is: Just because Python allows for OO doesn't mean it's okay to ignore the other parts. I should have the option of either A. letting the function fail and using exceptions (the OO/Python way), or B. calling a function that returns a value (success or error) instead of throwing an exception, and then having my function, in turn, return a sentinel value that indicates an error, so that errors bubble up the call stack and can be used as necessary (the procedural/C way). Just as C++ doesn't force you to use exceptions (you can use errno), Python shouldn't force it, either
  • Braden Best
    Braden Best over 4 years
    @EricLeschinski but there isn't a halting problem here. The program clearly raises an exception if an error occurs while parsing JSON. Therefore, the program knows when JSON input is invalid. Therefore, it is 100% possible to have a function that checks whether the input is valid without having to use try. #StopCanaryAbuse
  • djvg
    djvg about 3 years
    In current versions of Python 3, json.loads() throws a JSONDecodeError, which is (indeed) a subclass of ValueError, with some useful extra information. See source.
  • Eric Leschinski
    Eric Leschinski over 2 years
    Every piece of software that json encodes data must be the same at origin and destination for decoding. The "json standard" is not a standard. Making JSON just as portable as CSV flatfiles, HTML, XML, PDF, or any other data storage format. The format works perfectly with itself, but nothing else. To prove this to yourself, encode json data with one library, and decode it with a different library. It works for very trivial arrangements, but throw the list of naughty strings in and exercise every json datastructure, now none of the json parsers are compatible with any other. Bazinga.
  • Eric Leschinski
    Eric Leschinski about 2 years
    Don't let the word "Standard" in "jSon" throw you, no JSON encoder and decoder library is compatible with any other library. Make sure your JSON encoder/decoder is the same one at origin encoding and destination decoding. JSON is about as "standard" with itself as HTML, CSV, XML, XLS, ODS. That's why you bring canaries with you into the coal mine if you don't know where your json is from