35

私は最近 Python を使い始めました。JSON 文字列の 1 つを既存の JSON 文字列と連結しようとしています。私は Zookeeper も使用しているため、Python kazoo ライブラリを使用しているため、zookeeper ノードから既存の json 文字列を取得します。

# gets the data from zookeeper
data, stat = zk.get(some_znode_path)
jsonStringA = data.decode("utf-8")

印刷jsonStringAすると、このようになります-

{"error_1395946244342":"valueA","error_1395952003":"valueB"}

しかし、print json.loads(jsonString)そうすると、次のように出力されます-

{u'error_1395946244342': u'valueA', u'error_1395952003': u'valueB'}

ここjsonStringAには既存の JSON 文字列があります。これで、終了時に追加する必要がある別のキーと値のペアがありますjsonStringA-

以下は私のPythonコードです -

# gets the data from zookeeper
data, stat = zk.get(some_znode_path)
jsonStringA = data.decode("utf-8")

timestamp_in_ms = "error_"+str(int(round(time.time() * 1000)))
node = "/pp/tf/test/v1"
a,b,c,d = node.split("/")[1:]
host_info = "h1"
local_dc = "dc3"
step = "step2"

jsonStringAZookeeper から抽出した後、私の既存は次のようになります -

{"error_1395946244342":"valueA","error_1395952003":"valueB"}

次に、このキーと値のペアを追加する必要がありますjsonStringA-

"timestamp_in_ms":"Error Occured on machine "+host_info+" in datacenter "+ local_dc +" on the "+ step +" of process "+ c +"

要するに、キーと値のペアの下にマージする必要があります-

"error_1395952167":"Error Occured on machine h1 in datacenter dc3 on the step2 of process test"

したがって、最終的な JSON 文字列は次のようになります -

{"error_1395946244342":"valueA","error_1395952003":"valueB","error_1395952167":"Error Occured on machine h1 in datacenter dc3 on the step2 of process test"}

これは可能ですか?

4

6 に答える 6

34

a と b がマージする辞書であると仮定します。

c = {key: value for (key, value) in (a.items() + b.items())}

文字列を python 辞書に変換するには、次を使用します。

import json
my_dict = json.loads(json_str)

更新:文字列を使用した完全なコード:

# test cases for jsonStringA and jsonStringB according to your data input
jsonStringA = '{"error_1395946244342":"valueA","error_1395952003":"valueB"}'
jsonStringB = '{"error_%d":"Error Occured on machine %s in datacenter %s on the %s of process %s"}' % (timestamp_number, host_info, local_dc, step, c)

# now we have two json STRINGS
import json
dictA = json.loads(jsonStringA)
dictB = json.loads(jsonStringB)

merged_dict = {key: value for (key, value) in (dictA.items() + dictB.items())}

# string dump of the merged dict
jsonString_merged = json.dumps(merged_dict)

しかし、一般的に、あなたがやろうとしていることはベストプラクティスではないと言わざるを得ません。Python辞書について少し読んでください。


代替ソリューション:

jsonStringA = get_my_value_as_string_from_somewhere()
errors_dict = json.loads(jsonStringA)

new_error_str = "Error Ocurred in datacenter %s blah for step %s blah" % (datacenter, step)
new_error_key = "error_%d" % (timestamp_number)

errors_dict[new_error_key] = new_error_str

# and if I want to export it somewhere I use the following
write_my_dict_to_a_file_as_string(json.dumps(errors_dict))

実際には、配列を使用してすべてのエラーを保持するだけで、これらすべてを回避できます。

于 2014-03-27T20:30:36.720 に答える
10

両方の json 文字列を Python 辞書に読み込んでから組み合わせることができます。これは、各 json 文字列に一意のキーがある場合にのみ機能します。

import json

a = json.loads(jsonStringA)
b = json.loads(jsonStringB)
c = dict(a.items() + b.items())
# or c =  dict(a, **b)
于 2014-03-27T20:21:04.127 に答える
4

json オブジェクトのマージはかなり簡単ですが、キーの衝突を処理する際にいくつかの特殊なケースがあります。最大の問題は、1 つのオブジェクトが単純な型の値を持ち、もう 1 つのオブジェクトが複合型 (配列またはオブジェクト) を持つことに関係しています。それをどのように実装するかを決定する必要があります。Chef-solo に渡される json にこれを実装したときの選択は、オブジェクトをマージし、他のすべての場合に最初のソース オブジェクトの値を使用することでした。

これが私たちの解決策でした:

from collections import Mapping
import json


original = json.loads(jsonStringA)
addition = json.loads(jsonStringB)

for key, value in addition.iteritems():
    if key in original:
        original_value = original[key]
        if isinstance(value, Mapping) and isinstance(original_value, Mapping):
            merge_dicts(original_value, value)
        elif not (isinstance(value, Mapping) or 
                  isinstance(original_value, Mapping)):
            original[key] = value
        else:
            raise ValueError('Attempting to merge {} with value {}'.format(
                key, original_value))
    else:
        original[key] = value

最初のケースの後に別のケースを追加して、それらもマージする場合、または特殊なキーが発生した特定のケースの場合にリストをチェックすることができます。

于 2014-03-27T20:58:01.990 に答える
2

キーと値のペアを json 文字列に追加するには、dict.update :を使用できますdictA.update(dictB)

あなたの場合、これは次のようになります。

dictA = json.loads(jsonStringA)
dictB = json.loads('{"error_1395952167":"Error Occured on machine h1 in datacenter dc3 on the step2 of process test"}')

dictA.update(dictB)
jsonStringA = json.dumps(dictA)

キーの衝突により、値がdictBオーバーライドされることに注意してくださいdictA

于 2020-01-30T01:31:46.160 に答える
-2

合体するってどういうこと?JSON オブジェクトはキーと値のデータ構造です。この場合、キーと値は何でしょうか? 新しいディレクトリを作成し、古いデータを入力する必要があると思います:

d = {}
d["new_key"] = jsonStringA[<key_that_you_did_not_mention_here>] + \ 
               jsonStringB["timestamp_in_ms"]

マージ方法は明らかにあなた次第です。

于 2014-03-27T20:19:40.460 に答える