8

JSON を Web サーバーに送信し、JSON を取得する Python スクリプトを作成しようとしています。StackOverflow でいくつかの異なる例にパッチを当てましたが、ほとんど機能しているものがあると思います。

import urllib2
import json

url = "http://foo.com/API.svc/SomeMethod"
payload = json.dumps( {'inputs': ['red', 'blue', 'green']} )
headers = {"Content-type": "application/json;"}

req = urllib2.Request(url, payload, headers)
f = urllib2.urlopen(req)
response = f.read()
f.close()

data = json.loads(response) # <-- Crashes

最後の行で例外がスローされます。

ValueError: JSON オブジェクトをデコードできませんでした

を見るとresponse、有効な JSON が表示されますが、最初の数文字は BOM です。

>>> response
'\xef\xbb\xbf[\r\n  {\r\n    ... Valid JSON here

したがって、最初の 3 バイトを手動で削除すると、次のようになります。

data = json.loads(response[3::])

すべてが機能responseし、辞書に変わります。

私の質問:

jsonあなたがそれにBOMを与えるときにbarfsするのはちょっとばかげているようです. これがUTF8文字列であることを知らせ、そのように処理するためにurllib、ライブラリでできることはありますか? json最初の 3 バイトを手動で削除したくありません。

4

3 に答える 3

12

UTF-8 テキストの BOM は意味をなさないため、このサービスを実行している人に怒鳴る必要があります。BOM はバイト順を明確にするために存在し、UTF-8 はリトルエンディアンとして定義されています。

とはいえ、理想的には、バイトを使って何かをする前にバイトをデコードする必要があります。幸いなことに、Python には BOM を認識して削除するコーデックがあります: utf-8-sig.

>>> '\xef\xbb\xbffoo'.decode('utf-8-sig')
u'foo'

したがって、必要なのは次のとおりです。

data = json.loads(response.decode('utf-8-sig'))
于 2013-01-25T23:59:07.983 に答える
5

同じ問題を経験したのは私だけではなく、requestsの代わりにモジュールを使用urllib2している場合、Python 2.6 と 3.3 で機能するソリューションを次に示します。

import requests
r = requests.get(url, params=my_dict, auth=(user, pass))
print(r.headers['content-type'])  # 'application/json; charset=utf8'
if r.text[0] == u'\ufeff':  # bytes \xef\xbb\xbf in utf-8 encoding
    r.encoding = 'utf-8-sig'
print(r.json())
于 2014-05-09T15:35:03.547 に答える