我最近开始使用 Python,我正在尝试将我的 JSON 字符串之一与现有的 JSON 字符串连接起来。我也在使用 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"
我现有的
jsonStringA
从zookeeper中提取后会是这样的-
{"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"}
这可以吗?
从 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)
等等
编辑 2024 年 11 月 2 日:很确定我们现在可以做到
merged = dictA | dictB
假设a和b是你要合并的字典:
c = {key: value for (key, value) in (a.items() + b.items())}
要将字符串转换为 python 字典,请使用以下命令:
import json
my_dict = json.loads(json_str)
更新:使用strings的完整代码:
# 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))
实际上,如果你只使用一个数组来保存所有错误,你就可以避免所有这些。
您可以将两个 json 字符串加载到 Python 字典中,然后组合。仅当每个 json 字符串中都有唯一的键时,这才有效。
import json
a = json.loads(jsonStringA)
b = json.loads(jsonStringB)
c = dict(a.items() + b.items())
# or c = dict(a, **b)
合并 json 对象相当简单,但在处理按键冲突时有一些边缘情况。最大的问题与一个对象具有简单类型的值而另一个对象具有复杂类型(数组或对象)有关。您必须决定如何实施它。当我们为传递给 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
如果您还想合并这些列表,或者在遇到特殊键时的特定情况下,您可以在第一个案例之后添加另一个案例来检查列表。
要将键值对附加到 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
。
合并是什么意思? JSON 对象是键值数据结构。在这种情况下,键和值是什么?我认为您需要创建新目录并用旧数据填充它:
d = {}
d["new_key"] = jsonStringA[<key_that_you_did_not_mention_here>] + \
jsonStringB["timestamp_in_ms"]
合并方法显然取决于你。