【问题标题】:strange encoding issue of a JSON file with json.loads带有 json.loads 的 JSON 文件的奇怪编码问题
【发布时间】:2016-01-19 08:58:20
【问题描述】:

我有一个 JSON 文件,其中包含非 ascii 字符,主要是西班牙语重读元音。我已将此文件的编码设置为 utf-8(使用 vim 和 :set fileencoding=utf8)。

此文件的摘录,可供参考:

[
  {
    "location": "SRID=4326;POINT(-1.7944444440000000 43.3798499999999976)",
    "description": "",
    "name": "Fuenterrabía",
    "_id": 162
  },
...
]

注意名称字段中的“í”。

也就是说,我需要在我的代码中创建这些元素的可迭代对象,所以最后我将它发送到 FactoryBoy Factory 类的 create 方法。事情是,在这个过程中,角色变得一团糟,我得到了不知名的:

UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 143: ordinal not in range(128)

看看解析文件的代码:

    def _get_spot_data(self, filename):
        data_file = str(settings.ROOT_DIR('fixtures/meteo/'+filename))
        # Open file with utf-8 encoding
        f = codecs.open(data_file, 'r', 'utf8')
        data = simplejson.loads(f.read(), 'utf-8')
        return data

查看列表的第一个位置(用于参考的位置),我得到了:

{u'_id': 162, u'location': u'SRID=4326;POINT(-1.7944444440000000 43.3798499999999976)', u'name': u'Fuenterrab\xeda', u'description': u''}

如您所见,我似乎得到了 'í' 字符的字节表示。

我尝试过仅使用 open 而不是 codecs.open,尝试使用 json.loads 而不是 simplejson,但没有任何效果...我在这里做错了什么???

编辑:试图创建一个虚拟条目以查看我是否遇到相同的错误......因此我猜 FactorBoy 上的某些东西出了问题:

dummy_one = {u'surfspot_id': 162, u'location': u'SRID=4326;POINT(-1.7944444440000000 43.3798499999999976)', u'name': u'Fuenterrabía', u'description': u''}
SpotFactory(**dummy_one)

然后又报错了……

Traceback (most recent call last):
  File "/usr/lib/python2.7/logging/handlers.py", line 76, in emit
    if self.shouldRollover(record):
  File "/usr/lib/python2.7/logging/handlers.py", line 156, in shouldRollover
    msg = "%s\n" % self.format(record)
  File "/usr/lib/python2.7/logging/__init__.py", line 732, in format
    return fmt.format(record)
  File "/usr/lib/python2.7/logging/__init__.py", line 474, in format
    s = self._fmt % record.__dict__
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 143: ordinal not in range(128)
Logged from file base.py, line 397 

我必须说这不是阻塞问题,只是一个警告异常,但我不喜欢看到它,希望输出干净

谢谢!

【问题讨论】:

  • 我不明白。您是说“加载”引发异常 UnicodeDecodeError 吗?如果是这样,那么您给出的“查看列表的第一个位置......”的例子是什么?这不是“负载”的结果吗?
  • 不。之后由我从 FactoryBoy 获得的工厂的 create 方法引发,但它是传递 unicode 字符 'í' 的字节表示的结果......
  • 附加问题 你的 JSON 文件有 BOM 吗?
  • @Tomalak 你的意思是文件开头的编码?不,不是,我使用 vim 为该文件指定字符编码...我需要 BOM 是还是是?
  • 不,您绝对不这样做,为 UTF-8 文件设置 BOM 是可能的,但这是错误的。 vim 有一个选项(:h bomb),你可以将它与fenc 分开设置,这就是我问的原因。

标签: python json vim utf-8


【解决方案1】:

这很好用:

import json

with open(r'your/data.json') as f:
    data = json.load(f, encoding='utf-8')
    name = data[0]['name']

    print name
    print len(name)
    print name[-2:-1]

打印:

富特拉比亚 12 一世

但是,这个

print data[0]

仍然打印为:

{ 你'_id':162, u'位置': u'SRID=4326;POINT(-1.7944444440000000 43.3798499999999976)', u'name': u'Fuenterrab\xeda', 你'描述':你'' }

不要让自己被该输出所迷惑,字符串本身是 Unicode 并且包含正确的字符。

【讨论】:

  • 谢谢,但是为什么 factory/django.py 中的 _create 方法会失败呢?抛出异常,当我通过上面的字典时......
  • 我不知道。当您在 Python 脚本中手工制作虚拟数据而不是从 JSON 文件中检索数据时,它是否接受数据?
  • 是的,看起来很像 FactoryBoy 中的问题。
猜你喜欢
  • 2015-02-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-08
相关资源
最近更新 更多