2017-03-03 30 views
1

辞書の辞書をJSONファイルに保存するPythonコードをいくつか書きました。ファイルの最後に辞書を追加して、読み込んだり書き直したりする必要はありません。JSONファイルの最後に新しい要素を追加する方法は?

ここに私の最初のファイルは次のようになり、一例である:それは

{ "dict1": {"key1": 1.1, "key2": 1.2}, "dict2": {"key1": 2.1 "key2": 2.2}, "dict3": {"key1": 3.1, "key2": 3.2}} 

私は"a"モードでファイルを開くしようとしたが:

{ "dict1": {"key1": 1.1, "key2": 1.2}, "dict2": {"key1": 2.1 "key2": 2.2}} 

そして、私はそれに"dict3": {"key1": 3.1, "key2": 3.2}を追加します閉鎖}のために動作しません。だから私のファイルの最後の文字を上書きする方法や同じ結果を得るためのよりスマートな方法はありますか?

+1

なぜjsonをメモリにロードして、更新されたjsonを書きたくないのですか? –

+0

これを一般的な一般的な方法で行うと、巧妙になる可能性があります。しかし、JSONファイルの構造を事前に知っていれば、最終的な '}'文字の前にファイル内のすべてをコピーし、あなたの望むものを追加します(例の中にコンマをつけて) '。 – martineau

+0

@Budulianin私はこのプロセスを何度も繰り返さなければならないので、ファイルは少し巨大になるでしょう(私はいくつかのGoを期待しています)ので、可能ならば避けてください。 – Gabriel

答えて

1

を少しトリッキーかつ危険です。オリジナルのファイル形式にパッチを当てるだけです。多くの場合、ファイル全体のJSONを読み込み、データ項目を追加してから、ファイルを再シリアル化して書き換えるほうが簡単です。しかし、パフォーマンスやその他の理由から、ホットパッチは時には医師が注文したものです。だから、:

def append_to_json(filepath, data): 
    """ 
    Append data in JSON format to the end of a JSON file. 
    NOTE: Assumes file contains a JSON object (like a Python 
    dict) ending in '}'. 
    :param filepath: path to file 
    :param data: dict to append 
    """ 

    # construct JSON fragment as new file ending 
    new_ending = ", " + json.dumps(data)[1:-1] + "}\n" 

    # edit the file in situ - first open it in read/write mode 
    with open(filepath, 'r+') as f: 

     f.seek(0, 2)  # move to end of file 
     index = f.tell() # find index of last byte 

     # walking back from the end of file, find the index 
     # of the original JSON's closing '}' 
     while not f.read().startswith('}'): 
      index -= 1 
      if index == 0: 
       raise ValueError("can't find JSON object in {!r}".format(filepath)) 
      f.seek(index) 

     # starting at the original ending } position, write out 
     # the new ending 
     f.seek(index) 
     f.write(new_ending)  

# let 'er rip 
newval = {"dict3": {"key1": 3.1, "key2": 3.2}} 
append_to_json('data.json', newval) 

は、元のデータファイルが含まれていますこれを実行した後、data.jsonであると仮定すると:

{ "dict1": {"key1": 1.1, "key2": 1.2}, 
    "dict2": {"key1": 2.1, "key2": 2.2}, 
    "dict3": {"key1": 3.1, "key2": 3.2}} 

(ここではJSON出力は、読みやすくするために整列されたファイルでは、それはそうでしょう。非常に長い行です。)

私はこれを単純にしておくことで、理解しやすく理解しやすくなりました。実際には、JSONファイルの2番目の種類があります。これは、オブジェクトの配列であるレコード指向ファイル([ {}, ... {}])です。そのスタイルは '}'ではなく、 '}'で終わります。このルーチンのより開発されたバージョンでも、そのケースを探すでしょう。

+0

Thxあなた!私はesxactly私が探していたものだと思う! – Gabriel

-1

これを見ると、ファイルを開いた後にファイルの最後の文字を取得し、re.sub()を使用して最後の '}'を 'MyNewDic}'に置き換えます。あなたが代わりに先頭に終わり、余分な「」:

>>> s = '{ "dict1": {"key1": 1.1, "key2": 1.2}, "dict2": {"key1": 2.1 "key2": 2.2}}' 

>>> re.sub(r'}$',',"dict3": {"key1": 3.1, "key2": 3.2}}',s) 

それがプットこれを与える:場所にデータファイルを編集する

'{ "dict1": {"key1": 1.1, "key2": 1.2}, "dict2": {"key1": 2.1 "key2": 2.2},"dict3": {"key1": 3.1, "key2": 3.2}}' 
+0

すべてのjsonをメモリにロードするのは解決策ではありません。 –

0

巨大なJSON文字列を作成する必要はありません。もしそれが本当に"私のRAMよりも大きい"なら、それではどうすれば遅くを使ってとにかく?

私はこのような1行に1つのエントリ(つまり、単に1行に1つの json.dumps(dictitem)だ)であなたが、例えば、適切なデータベースまたは単純な形式を使用することをお勧め

:次に、あなたは、単にエントリ/行を追加することができます

["dict1", {"key1": 1.1, "key2": 1.2}] 
["dict2", {"key1": 2.1, "key2": 2.2}] 
["dict3", {"key1": 3.1, "key2": 3.2}] 

ファイルを解析し、ファイルを解析することもまだ簡単です。そしてメモリ効率が良い。

with open('data.txt') as f: 
    for line in f: 
     key, value = json.loads(line) 
     ... 
+0

ファイルを簡単に追加できるように構造化することをお勧めします。このための標準でさえ、[RFC 7464](https://tools.ietf.org/html/rfc7464)です。私はあなたが示唆している特定の配列ごとのフォーマットで、美徳を見ることはできません。これはJSONですが、キー名と値の間の関係は削除されています。なぜ1行に1つのオブジェクトがないのですか? '{" dict3 ":{" key1 ":3.1、" key2 ":3.2}}'?これにより、追加能力とオブジェクト構造の両方が保持されます。 –

+0

@JonathanEunice私は、あなたのことは、執筆と読書の両方のためのより多くの仕事だと思います。あるいは、 'key、value = json.loads(line)'のような何かをすることができますか?あるいは、 'dict(map(json.loads、f))'のようにファイル全体から辞書全体を作成する(メモリが許せば)。私はちょうどファイルに辞書の項目を書くことを考えている、辞書の項目は辞書ではなく、ペアです。 –

+0

キーと値のペアについての実線の点。しかし、完全な辞書は管理するのも難しくありません。行ごとに 'd = json.loads(line)'、または 'd = {}; for f:d.update(json.loads(line)) 'を実行します。 –

関連する問題