【问题标题】:simplejson: loading spanish characters -- utf-8simplejson: 加载西班牙语字符 -- utf-8
【发布时间】:2013-02-27 21:25:25
【问题描述】:

我正在尝试使用 Python 的 simplejson 加载一些地理数据。

<!-- language: lang-py -->
string = file("prCounties.txt","r").read().decode('utf-8')  
d = simplejson.loads(string)    

文本文件有一个波浪号,单词应该是 Añasco 而不是 SimpleJson 不解析的 u"A\xf1asco"。来源是geoJson file from github

{"type": "FeatureCollection", "properties": {"kind": "state", "state": "PR"}, "features": [[{"geometry": {"type": "MultiPolygon", "coordinates": [[[[-67.122, 18.3239], [-67.0508, 18.3075], [-67.0398, 18.291], [-67.0837, 18.2527], [-67.122, 18.2417], [-67.1603, 18.2746], [-67.1877, 18.2691], [-67.2261, 18.2965], [-67.1822, 18.3129], [-67.1275, 18.3184]]]]}, "type": "Feature", "properties": {"kind": "county", "name": u"A\xf1asco", "state": "PR"}}]]}

Python 给了我错误simplejson.decoder.JSONDecodeError: Expecting object


我用来从 GitHub 加载生成prCounties.txt 的脚本。变量counties 是与相关 GEOjson 数据的位置相关的字符串列表。

很明显,这不是保存这些数据的正确方法:

<!-- language: lang-py -->
countyGeo = [ ]

for x in counties:      
    d = simplejson.loads(urllib.urlopen("https://raw.github.com/johan/world.geo.json/master/countries/USA/PR/%s" % (x)).read())         
    countyGeo += [ d["features"][0]]
    d["features"][0]=countyGeo  
file("prCounties.txt", "w").write(str(d))

编辑:在最后一行,我将str 替换为simplejson.dumps。我猜它现在可以正确编码。 file("prCounties.txt", "w").write(simplejson.dumps(d))

【问题讨论】:

  • u"A\xf1asco"u"Añasco" (和 u"A\u00f1asco" )相同。
  • 您将其视为u"A\xf1asco" 的原因是(在Python 2.x 中),unicode 字符串的repr 会转义任何非ASCII 字符。例如,在您的交互式解释器中,u'ñ' 将打印出u'\xf1',但print u'ñ' 将打印出ñ
  • 还有其他原因 simplejson 没有正确加载吗?
  • 是的,因为您的字符串不是 JSON object,而是 dict 的 Python repr。它们通常非常相似,但它们不是一回事,你不能对它们一视同仁。特别是,您不能在 JSON 对象中包含 u"Añasco";您需要在普通双引号中使用 UTF-8 字符串文字。
  • 好的,这正是我所怀疑的:您在每个文件上调用loads,然后写下其中的str,然后尝试在str 上调用loads。当然,这是行不通的。如果您只使用dumps 而不是str,您可以稍后将其加载回来。或者只保留 JSON 字符串,并将名称映射到 JSON 字符串而不是对象。或者……真的,如果你只是想清楚你想要做什么,应该很容易想到有明显反向操作的东西,然后去做。

标签: python json internationalization simplejson


【解决方案1】:

这里有两个问题。第一:

string = file("prCounties.txt","r").read().decode('utf-8')

你为什么要解码它? JSON 显式采用 UTF-8 字符串。这是 JSON 定义的一部分。 simplejson 可以处理 Unicode 字符串这一事实使它更易于使用,但它通过将它们编码回 UTF-8 来有效地处理它们,所以……为什么不一开始就这样呢?

更重要的是,您的数据来自哪里?如果 prCounties.txt 中包含 u"Añasco",则它不是 JSON。您不能仅仅因为它们看起来相似就将某些东西编码为一种标准并解码为完全不同的标准。

例如,如果您执行了open('prCounties.txt', 'w').write(repr(my_dict)),则必须使用 Python 的repr 解析器(可能是ast.literal_eval,或者您必须自己编写一些东西)来读回它。

或者,如果您想将数据解析为 JSON,请首先将其写为 JSON。


根据您的评论,数据是从https://raw.github.com/johan/world.geo.json/master/countries/USA/PR/Añasco.geo.json 读取的

该 URL 的原始内容是:

{"type":"FeatureCollection","properties":{"kind":"state","state":"PR"},"features":[
{"type":"Feature","properties":{"kind":"county","name":"Añasco","state":"PR"},"geometry":{"type":"MultiPolygon","coordinates":[[[[-67.1220,18.3239],[-67.0508,18.3075],[-67.0398,18.2910],[-67.0837,18.2527],[-67.1220,18.2417],[-67.1603,18.2746],[-67.1877,18.2691],[-67.2261,18.2965],[-67.1822,18.3129],[-67.1275,18.3184]]]]}}
]}

您会注意到那里没有"name": u"Añasco"(或"name": u"A\xf1asco",或类似的东西)。您只需调用 read 即可阅读此内容——无需从 UTF-8 或其他任何内容进行解码——只需将其传递给 simplejson.loads 即可:

$ curl -O https://raw.github.com/johan/world.geo.json/master/countries/USA/PR/Añasco.geo.json
$ cp Añasco.geo.json prCounties.txt
$ python
>>> import simplejson
>>> string = file("prCounties.txt","r").read()
>>> d = simplejson.loads(string)
>>> print d
{u'type': u'FeatureCollection', u'properties': {u'kind': u'state', u'state': u'PR'}, u'features': [{u'geometry': {u'type': u'MultiPolygon', u'coordinates': [[[[-67.122, 18.3239], [-67.0508, 18.3075], [-67.0398, 18.291], [-67.0837, 18.2527], [-67.122, 18.2417], [-67.1603, 18.2746], [-67.1877, 18.2691], [-67.2261, 18.2965], [-67.1822, 18.3129], [-67.1275, 18.3184]]]]}, u'type': u'Feature', u'properties': {u'kind': u'county', u'name': u'A\xf1asco', u'state': u'PR'}}]}

看,完全没有错误。

在某个地方,您已经对这些数据进行了一些处理,以将其转换为非 JSON 的其他内容。我的猜测是,除了做了一堆不必要的额外decodeencode 调用之外,你还做了一个simplejson.loads,然后尝试重新simplejson.loads reprdict你回来了。或者,也许您已经对一个充满已编码 JSON 字符串的 dict 进行了 JSON 编码。无论您做了什么,错误所在是该代码,而不是您向我们展示的代码。

最简单的解决方法可能是首先正确生成prCounties.txt。每行只需要 70 多次下载,可能需要 2 行 bash 或 4 行 Python 才能完成……

【讨论】:

  • 它来自https://github.com/johan/world.geo.json/blob/master/countries/USA/PR/Añasco.geo.json 文件名,文本中有一个
  • 是的,内容中有… "name":"Añasco",。你从哪里得到你的… "name": u"Añasco" …?您显然已经对文件进行了某种处理,将其从 JSON 转换为非 JSON。如果你只是解析文件中的实际原始数据,它可以正常工作。
  • hmm... 我使用urllib.urlopen 从 Github 读取它(以及大约 75 个类似文件),我将它们合并并保存到一个文件中。然后我打开了那个文件,这个烂摊子就开始了。
  • 让我们忽略urllib.urlopen 已被弃用的事实,因为这与这里无关。您显然不只是将在每个 urlopen 上调用 read 的结果连接到一个文件中,否则您将不会得到这个。如果您不再拥有用于生成prCounties.txt 文件的代码,也许最简单的方法就是编写新代码以正确生成它?
  • 我得到:未定义的名称“文件”,也许我错过了导入?抱歉,我是 Python 新手
【解决方案2】:

您的输入文件不是有效的 JSON。在"A\xf1asco" 字符串之前有一个u,这是Python 语法,不是JSON 语法。应该是:

"name":"A\xf1asco",

这行得通:

>>> import json
>>> json.loads(u'{"name":"A\xf1asco"}')
{u'name': u'A\xf1asco'}

【讨论】:

  • +1。但是你也不需要外部的u;通常你会得到 JSON 作为 UTF-8。例如,如果您将{'name': u'Añasco'} 编码为 JSON,您将得到{"name": "A\xc3\xb1asco"},这将解码为完全相同的内容。 (换句话说,json.loads 在解码之前对您的输入有效地调用encode('utf-8')。)
  • 我怀疑 json 解码工作得很好,但 OP 现在看到的是 Python 文字..
  • @MartijnPieters:OP 说他收到“simplejson.decoder.JSONDecodeError”。也许他正在尝试 JSON 解码,然后重新 JSON-decode 结果的 repr 之类的。
【解决方案3】:

您必须删除 prCounties.txt 文件中的“u”(如前所述)。然后你可以使用这段代码,它可以很好地以 simplejson.loads() 函数可读的格式创建变量“string”:

import simplejson
string = file("prCounties.txt", "r").read().decode("string-escape")
string = unicode(string, "latin-1")
simplejson.loads(string)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-18
    • 1970-01-01
    • 2012-10-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多