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

How to merge two json string in Python?

我最近开始使用python,并尝试将我的一个JSON字符串与现有的JSON字符串连接起来。我还与ZooKeeper一起工作,因此在使用python-kazoo库时,从ZooKeeper节点获取现有的JSON字符串。

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

如果我打印jsonStringA,它会给我这样的效果。-

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

但是如果我这样做,那么它就会像这样打印出来。-

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

这里,jsonStringA将有我现有的json字符串。现在我有了另一个键值对,我需要在现有的jsonStringA中添加它。-

下面是我的python代码-

1
2
3
4
5
6
7
8
9
10
# 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"

我现有的jsonStringA在从动物园管理员那里提取之后会变成这样。-

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

现在我需要在jsonStringA中附加这个键值对。-

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

所以简而言之,我需要合并下面的键值对-

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

所以最终的json字符串将如下所示-

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

这可以吗?


假设A和B是要合并的字典:

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

要将字符串转换为python字典,请使用以下方法:

1
2
import json
my_dict = json.loads(json_str)

更新:使用字符串的完整代码:

1
2
3
4
5
6
7
8
# test cases for jsonStringA and jsonStringB according to your data input
jsonStringA = '{"error_1395946244342":"valueA","error_1395952003":"valueB
<div class="suo-content">[collapse title=""]<ul><li>不好意思弄混了。我现在更新了我的问题,所以现在应该有意义了。</li><li>你用的是字符串还是字典?我给你的例子是正确的。</li><li>我又更新了问题。正如我最近从python开始的,所以不确定dictionary在这里是什么意思。我已经更新了我的<wyn>jsonStringA</wyn>如何打印出来的问题。我想需要附加的字符串是一个简单的字符串。</li><li>我更新了我的答案。现在我使用普通的JSON字符串作为输入。请仔细阅读,以便您了解字符串和字典的情况。</li><li>这很有道理……最后一个问题是,如何正确地使用<wyn>jsonStringB</wyn>的所有值?因为我需要与变量中的所有值进行键值配对。</li><li>请参见更新的代码。%s就地添加一个字符串类型的参数,%d添加一个整数。所有参数都在末尾的元组中。(a,b,c,…)</li><li>希望有帮助,如果您对结果满意,请将问题标记为已回答。</li><li>我一定会的。但是你能告诉我这个方法有什么问题吗?为什么你说这不是正确的方法?只是想知道。</li><li>除了时间戳提供的优先级之外,这些键似乎没有太大的重要性。因此维护字典比维护数组要复杂得多。尤其是如果您有所有这些字符串转换/json解码。除非您在后面的阶段需要这个数据结构,上面的代码示例中没有显示。就个人而言,在编码方面,我喜欢"保持简单愚蠢"的想法,当然,我最喜欢的是"少即多":)</li><li>谢谢你的帮助。是的,它们有些用处。我将把这个JSON字符串写回ZooKeKER,然后我有一个Java程序运行,它保持对那个节点的监视,只提取最新的时间戳。不管怎样,告诉我一件事:假设这个方法<wyn>get_my_value_as_string_from_somewhere()</wyn>返回空字符串,那么我能用new_error_str生成正确的JSON字符串吗?</li><li>不,不能将空字符串解码为JSON。你可以做一些类似于<wyn>jsonStringA = get_my_value_as_string_from_somewhere() or '
{}'</wyn>的事情。是有效的JSON对象。</li><li>有道理。。但在这种情况下,如何检查<wyn>jsonStringA</wyn>是否为空,然后将<wyn>jsonStringA</wyn>分配给<wyn>{}</wyn>?否则保持原样。这可以吗?</li><li>你在我最后的评论中看到的就是你想做的。他们Python道:)</li></ul>[/collapse]</div><hr><P>您可以将这两个JSON字符串加载到Python字典中,然后进行组合。只有在每个JSON字符串中都有唯一的键时,这才有效。</P>[cc lang="python"]    import json

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


从python 3.5开始,可以将两个dict合并为:

1
merged = {**dictA, **dictB}

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

所以:

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

等。


Merging json objects is fairly straight forward but has a few edge cases when dealing with key collisions. The biggest issues have to do with one object having a value of a simple type and the other having a complex type (Array or Object). You have to decide how you want to implement that. Our choice when we implemented this for json passed to chef-solo was to merge Objects and use the first source Object's value in all other cases.

This was our solution:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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

如果要合并列表,也可以在第一个案例之后添加另一个案例,或者在遇到特殊键时检查特定案例。


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

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

合并方法显然取决于您。