解码json时的ValueError

4 投票
2 回答
12644 浏览
提问于 2025-04-17 05:39
import json
import urllib
import re
import binascii 

def asciirepl(match):
  s = match.group()  
  return binascii.unhexlify(s[2:])  

query = 'google'
p = urllib.urlopen('http://www.google.com/dictionary/json?callback=a&q='+query+'&sl=en&tl=en&restrict=pr,de&client=te')
page = p.read()[2:-10] #As its returned as a function call

#To replace hex characters with ascii characters
p = re.compile(r'\\x(\w{2})')
ascii_string = p.sub(asciirepl, page)

#Now decoding cleaned json response
data = json.loads(ascii_string)

运行这个程序时,我遇到了这个错误,

shadyabhi@archlinux /tmp $ python2 define.py                                                                                                                                      
Traceback (most recent call last):
  File "define.py", line 19, in <module>
    data = json.loads(ascii_string)
  File "/usr/lib/python2.7/json/__init__.py", line 326, in loads
    return _default_decoder.decode(s)
  File "/usr/lib/python2.7/json/decoder.py", line 366, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/lib/python2.7/json/decoder.py", line 382, in raw_decode
    obj, end = self.scan_once(s, idx)
ValueError: Expecting , delimiter: line 1 column 403 (char 403)

我觉得这个json没有任何错误,因为我是从谷歌的服务器上收到的。 我所做的只是去掉了一些十六进制字符。任何帮助都会非常感谢。

2 个回答

2

字符403是“文本”中的第一个嵌入引号 - 这不是有效的json格式:

{
   "type":"url",
   "text":"<a href="http://www.people-communicating.com/jargon-words.html">http://www.people-communicating.com/jargon-words.html</a>",
   "language":"en"
}

这是服务器返回的内容 - 注意,没有嵌入的引号:

{
    "type":"url",
    "text":"\\x3ca href\\x3d\\x22http://www.people-communicating.com/jargon-words.html\\x22\\x3ehttp://www.people-communicating.com/jargon-words.html\\x3c/a\\x3e",
    "language":"en"
}

最好的做法是先解码json,然后在需要的时候对每个字符串进行去十六进制处理。

编辑:如果这真的是无效的JSON,就像Karl Knechtel在评论中说的那样,应该告诉谷歌他们的API有问题。如果Python的实现对有效的JSON处理不当,也应该让他们知道去修复它。无论你采取什么变通办法,如果这个问题得到解决,都应该容易去掉。

3

解码\x转义字符可能会产生"符号,这些符号在JSON数据中的“字符串”里出现时需要重新转义。

def asciirepl(match):
  chr = binascii.unhexlify(match.group()[2:])
  return '\\' + chr if chr in ('\\"') else chr

不过这样做还是不能处理控制字符;所以你可能想把\x转义字符转换成\u转义字符,这在JSON标准中有说明,并且可以被json模块解析。这样做还有一个好处,就是更简单 :)

def asciirepl(match):
  return '\\u00' + match.group()[2:]

撰写回答