変数にJSONデータを保存していますdata
。
これをテスト用のテキストファイルに書き込みたいので、毎回サーバーからデータを取得する必要はありません。
現在、私はこれを試しています:
obj = open('data.txt', 'wb')
obj.write(data)
obj.close
そして、私はこのエラーを受け取ります:
TypeError:dictではなく文字列またはバッファである必要があります
これを修正する方法は?
実際のJSON部分を忘れました-data
辞書であり、まだJSONでエンコードされていません。互換性を最大化するために、次のように記述します(Python 2および3)。
import json
with open('data.json', 'w') as f:
json.dump(data, f)
最新のシステム(つまり、Python 3とUTF-8のサポート)では、次のコマンドを使用してより優れたファイルを作成できます。
import json
with open('data.json', 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=4)
Python 2で受け入れられている回答で、ASCIIでエンコードされたファイルではなくutf8でエンコードされたファイルを取得するには、次のようにします。
import io, json
with io.open('data.txt', 'w', encoding='utf-8') as f:
f.write(json.dumps(data, ensure_ascii=False))
Python 3のコードはより単純です:
import json
with open('data.txt', 'w') as f:
json.dump(data, f, ensure_ascii=False)
Windowsでは、encoding='utf-8'
への引数open
はまだ必要です。
データのエンコードされたコピー(の結果)をメモリに保存しないようにし、Python 2と3の両方でutf8でエンコードされdumps
たバイト文字列を出力するには、次を使用します。
import json, codecs
with open('data.txt', 'wb') as f:
json.dump(data, codecs.getwriter('utf-8')(f), ensure_ascii=False)
このcodecs.getwriter
呼び出しはPython3では冗長ですが、Python2では必要です
読みやすさとサイズ:
を使用すると、ensure_ascii=False
読みやすさが向上し、サイズが小さくなります。
>>> json.dumps({'price': '€10'})
'{"price": "\\u20ac10"}'
>>> json.dumps({'price': '€10'}, ensure_ascii=False)
'{"price": "€10"}'
>>> len(json.dumps({'абвгд': 1}))
37
>>> len(json.dumps({'абвгд': 1}, ensure_ascii=False).encode('utf8'))
17
またはの引数にフラグindent=4, sort_keys=True
(dinos66で提案されている)を追加することにより、読みやすさをさらに向上させます。このようにして、ファイルサイズが少し大きくなりますが、jsonファイルで適切にインデントされた並べ替えられた構造を取得できます。dump
dumps
私は前述の答えを少し変更して答えます。それは、人間の目がよりよく読めるように、きれいなJSONファイルを作成することです。このために、4つのスペース文字をそのまま通過させれば、準備は完了ですsort_keys
。また、ASCIIコードがJSONファイルに書き込まれないように注意してください。True
indent
with open('data.txt', 'w') as outfile:
json.dump(jsonData, outfile, sort_keys = True, indent = 4,
ensure_ascii = False)
# -*- coding: utf-8 -*-
import json
# Make it work for Python 2+3 and with Unicode
import io
try:
to_unicode = unicode
except NameError:
to_unicode = str
# Define data
data = {'a list': [1, 42, 3.141, 1337, 'help', u'€'],
'a string': 'bla',
'another dict': {'foo': 'bar',
'key': 'value',
'the answer': 42}}
# Write JSON file
with io.open('data.json', 'w', encoding='utf8') as outfile:
str_ = json.dumps(data,
indent=4, sort_keys=True,
separators=(',', ': '), ensure_ascii=False)
outfile.write(to_unicode(str_))
# Read JSON file
with open('data.json') as data_file:
data_loaded = json.load(data_file)
print(data == data_loaded)
のパラメータの説明json.dump
:
indent
:4つのスペースを使用して、各エントリをインデントします。たとえば、新しいdictが開始されたとき(そうでない場合は、すべてが1行になります)。sort_keys
:辞書のキーを並べ替えます。これは、jsonファイルをdiffツールと比較したり、バージョン管理下に置いたりする場合に便利です。separators
:Pythonが末尾の空白を追加しないようにするため私のユーティリティパッケージmpu
を見て、非常にシンプルで覚えやすいものを見つけてください。
import mpu.io
data = mpu.io.read('example.json')
mpu.io.write('example.json', data)
{
"a list":[
1,
42,
3.141,
1337,
"help",
"€"
],
"a string":"bla",
"another dict":{
"foo":"bar",
"key":"value",
"the answer":42
}
}
.json
アプリケーションでは、次のことが重要になる場合があります。
構成ファイルを作成する方法を探している場合は、私の短い記事「Pythonでの構成ファイル」を読むことをお勧めします。
ギリシャ語や私のような他の「エキゾチック」な言語をダンプしようとしているが、平和の記号(\ u262E)などの奇妙な文字やjson形式のデータに含まれることが多いその他の文字に問題(Unicodeエラー)がある場合Twitterの場合、解決策は次のようになります(sort_keysは明らかにオプションです)。
import codecs, json
with codecs.open('data.json', 'w', 'utf8') as f:
f.write(json.dumps(data, sort_keys = True, ensure_ascii=False))
コメントを追加するのに十分な評判がないので、この厄介なTypeErrorの発見のいくつかをここに書きます。
基本的に、これはPython 2json.dump()
の関数のバグだと思います。パラメータを指定してファイルを開いても、非ASCII文字を含むPython(辞書/リスト)データをダンプすることはできません。(つまり、あなたが何をしても)。ただし、Python2と3の両方で動作します。encoding = 'utf-8'
json.dumps()
これを説明するために、phihagの答えをフォローアップします。彼の答えのコードは、非ASCII文字が含まれているTypeError: must be unicode, not str
場合、例外を除いてPython2で壊れます。data
(Python 2.7.6、Debian):
import json
data = {u'\u0430\u0431\u0432\u0433\u0434': 1} #{u'абвгд': 1}
with open('data.txt', 'w') as outfile:
json.dump(data, outfile)
ただし、Python3では正常に機能します。
JSONを使用してファイルにデータを書き込みます。json.dump()またはjson.dumps()を使用します。このように記述して、データをファイルに保存します。
import json
data = [1,2,3,4,5]
with open('no.txt', 'w') as txtfile:
json.dump(data, txtfile)
リスト内のこの例は、ファイルに保存されます。
json.dump(data, open('data.txt', 'wb'))
インデント付きのJSONを作成するには、「きれいに印刷」します。
import json
outfile = open('data.json')
json.dump(data, outfile, indent=4)
また、不適切にフォーマットされたJSONをデバッグする必要があり、役立つエラーメッセージが必要な場合はimport simplejson
、代わりにライブラリを使用しimport json
てください(関数は同じである必要があります)
これまでのすべての答えはここで正しいです。これは非常に単純な例です。
#! /usr/bin/env python
import json
def write_json():
# create a dictionary
student_data = {"students":[]}
#create a list
data_holder = student_data["students"]
# just a counter
counter = 0
#loop through if you have multiple items..
while counter < 3:
data_holder.append({'id':counter})
data_holder.append({'room':counter})
counter += 1
#write the file
file_path='/tmp/student_data.json'
with open(file_path, 'w') as outfile:
print("writing file to: ",file_path)
# HERE IS WHERE THE MAGIC HAPPENS
json.dump(student_data, outfile)
outfile.close()
print("done")
write_json()
パンダのデータフレームをjson形式を使用してファイルに書き込もうとしている場合は、これをお勧めします
destination='filepath'
saveFile = open(destination, 'w')
saveFile.write(df.to_json())
saveFile.close()
受け入れられた答えは大丈夫です。しかし、それを使用して「jsonシリアル化可能ではありません」というエラーが発生しました。
これが私open("file-name.json", 'w')
が出力としてそれを修正した方法です:
output.write(str(response))
作成するjsonファイルには二重引用符がないため、適切な修正ではありませんが、すばやくダーティなものを探している場合は最適です。
JSONデータは次のようにファイルに書き込むことができます
hist1 = [{'val_loss': [0.5139984398465246],
'val_acc': [0.8002029867684085],
'loss': [0.593220705309384],
'acc': [0.7687131817929321]},
{'val_loss': [0.46456472964199463],
'val_acc': [0.8173602046780344],
'loss': [0.4932038113037539],
'acc': [0.8063946213802453]}]
ファイルへの書き込み:
with open('text1.json', 'w') as f:
json.dump(hist1, f)
これは、の使用法に関する追加のヒントですjson.dumps
(これは、質問の問題に対する答えではありませんが、numpyデータ型をダンプする必要がある人のためのトリックです):
ディクショナリにNumPyデータ型がありjson.dumps()
、追加のパラメータが必要な場合、クレジットはTypeErrorに移動します。タイプ'ndarray'のオブジェクトはJSONシリアル化可能ではなく、次のようなエラーも修正TypeError: Object of type int64 is not JSON serializable
されます。
class NumpyEncoder(json.JSONEncoder):
""" Special json encoder for np types """
def default(self, obj):
if isinstance(obj, (np.int_, np.intc, np.intp, np.int8,
np.int16, np.int32, np.int64, np.uint8,
np.uint16, np.uint32, np.uint64)):
return int(obj)
elif isinstance(obj, (np.float_, np.float16, np.float32,
np.float64)):
return float(obj)
elif isinstance(obj, (np.ndarray,)):
return obj.tolist()
return json.JSONEncoder.default(self, obj)
そして、実行します:
import json
#print(json.dumps(my_data[:2], indent=4, cls=NumpyEncoder)))
with open(my_dir+'/my_filename.json', 'w') as f:
json.dumps(my_data, indent=4, cls=NumpyEncoder)))
np.array()の場合は、リストの代わりに文字列を返すこともできます。これは、配列が行に分散されたリストとして出力されるため、大きな配列または多数の配列がある場合に出力が大きくなるためです。警告:ダンプされたディクショナリからアイテムにアクセスして、元の配列として戻すことはより困難です。ただし、配列の文字列だけを使用してもかまわない場合は、辞書が読みやすくなります。次に交換します:
elif isinstance(obj, (np.ndarray,)):
return obj.tolist()
と:
elif isinstance(obj, (np.ndarray,)):
return str(obj)
あるいは単に:
else:
return str(obj)