Reputation: 300
In a python script I am parsing the return of
gsettings get org.gnome.system.proxy ignore-hosts
which looks like it should be properly formatted JSON
['localhost', '127.0.0.0/8']
however, when passing this output to json.loads it throws
ValueError: No JSON object could be decoded
I make the call to gsettings via:
import subprocess
proc = subprocess.Popen(["gsettings", "get", "org.gnome.system.proxy", "ignore-hosts"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout,stderr = proc.communicate()
which assigns "['localhost', '127.0.0.0/8']\n"
to stdout
.
Then I strip the newline and pass to json.loads:
ignore = json.loads(stdout.strip("\n"))
But, this throws a ValueError
.
I've tracked the issue down to the string being defined by single-quotes or double-quotes as shown in the following snippet:
# tested in python 2.7.3
import json
ignore_hosts_works = '["localhost", "127.0.0.0/8"]'
ignore_hosts_fails = "['localhost', '127.0.0.0/8']"
json.loads(ignore_hosts_works) # produces list of unicode strings
json.loads(ignore_hosts_fails) # ValueError: No JSON object could be decoded
import string
table = string.maketrans("\"'", "'\"")
json.loads(string.translate(ignore_hosts_fails, table)) # produces list of unicode strings
Why is ignore_hosts_fails
not successfully parsed by json.loads
without swapping the quote types?
In case it might matter, I'm running Ubuntu 12.04 with Python 2.7.3.
Upvotes: 1
Views: 5581
Reputation: 11
Yes it cares for valid json. But you can tweak Simple json code to parse this Unquoted and single quoted json strings.
I have given my answer on this post
Single versus double quotes in json loads in Python
Upvotes: 0
Reputation: 38177
As said before, that is invalid JSON. To parse, there are two other possibilities: use either demjson
or yaml
>>> demjson.decode(" ['localhost', '127.0.0.0/8']")
[u'localhost', u'127.0.0.0/8']
>>> yaml.load(" ['localhost', '127.0.0.0/8']")
['localhost', '127.0.0.0/8']
Upvotes: 0
Reputation: 1121914
From the JSON RFC 7159:
string = quotation-mark *char quotation-mark
[...]
quotation-mark = %x22 ; "
JSON strings must use "
quotes.
You can parse that list as a Python literal instead, using ast.literal_eval()
:
>>> import ast
>>> ast.literal_eval("['localhost', '127.0.0.0/8']")
['localhost', '127.0.0.0/8']
Upvotes: 5
Reputation: 9637
JSON is not just JavaScript.
JSON strings are double quoted according to the spec pdf or json.org.
JSON object keys are strings.
You must use double quotes for your strings and keys (to follow the spec). Many JSON parsers will be more permissive.
From object
definition:
An object structure is represented as a pair of curly bracket tokens surrounding zero or more name/value pairs.
A name is a string. A single colon token follows each name, separating the name from the value. A single comma token separates a value from a following name.
From string
definition:
A string is a sequence of Unicode code points wrapped with quotation marks (U+0022).
That U+0022
is the (double) quotation mark: "
.
Upvotes: 0