如何在Python中合并两个json字符串?

时间:2014-03-27 20:13:04

标签: python json string kazoo

我最近开始使用Python,我试图将我的一个JSON String与现有的JSON String连接起来。我也在使用Zookeeper,所以我从zookeeper节点获取现有的json字符串,因为我正在使用Python kazoo库。

# 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"

从zookeeper中提取后,我现有的jsonStringA将是这样的 -

{"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"}

这可能吗?

6 个答案:

答案 0 :(得分:21)

假设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))

实际上,如果您只是使用数组来保存所有错误,那么您可以避免所有这些。

答案 1 :(得分:6)

您可以将两个json字符串加载到Python Dictionaries中,然后组合。这只有在每个json字符串中都有唯一键时才有效。

    import json

    a = json.loads(jsonStringA)
    b = json.loads(jsonStringB)
    c = dict(a.items() + b.items())
    # or c =  dict(a, **b)

答案 2 :(得分:3)

从Python 3.5开始,您可以使用以下命令合并两个字典:

merged = {**dictA, **dictB}

https://www.python.org/dev/peps/pep-0448/

所以:

jsonMerged = {**json.loads(jsonStringA), **json.loads(jsonStringB)}
asString = json.dumps(jsonMerged)

答案 3 :(得分:1)

合并json对象非常简单,但在处理关键冲突时有一些边缘情况。最大的问题与一个具有简单类型值的对象和另一个具有复杂类型(数组或对象)的对象有关。您必须决定如何实现它。当我们为json传递给chef-solo时,我们的选择是合并Objects并在所有其他情况下使用第一个源Object值。

这是我们的解决方案:

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

您可以在第一个案例之后添加另一个案例以检查列表是否也要合并这些案例,或者遇到特殊键时的特定情况。

答案 4 :(得分:1)

要将键值对附加到json字符串,可以使用dict.updatedictA.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

答案 5 :(得分:0)

合并是什么意思? JSON对象是键值数据结构。在这种情况下,什么是关键和价值?我认为您需要创建新目录并使用旧数据填充它:

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

合并方法显然取决于你。