¿Cómo fusionar dos cadenas json en Python?

Recientemente empecé a trabajar con Python y estoy tratando de concatenar una de mis cadenas JSON con las existentes. También estoy trabajando con Zookeeper, así que obtengo la cadena json existente del nodo zookeeper ya que estoy utilizando la biblioteca kazoo de Python.

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

Si jsonStringA me da así:

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

Pero si print json.loads(jsonString) , se imprime así:

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

Aquí jsonStringA tendrá mi cadena JSON existente. Ahora tengo otro par clave-valor que necesito agregar en el jsonStringA

Abajo está mi código de 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" 

Mi jsonStringA existente será así después de extraerlo del zookeeper:

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

Ahora necesito agregar este par clave-valor en jsonStringA

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

Entonces, en resumen, necesito unir el par clave-valor por debajo.

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

Así que la cadena JSON final se verá así:

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

¿Es posible hacerlo?

Asumiendo que a y b son los diccionarios que desea combinar:

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

Para convertir su cadena al diccionario de Python, use lo siguiente:

 import json my_dict = json.loads(json_str) 

Actualización: código completo usando cadenas :

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

Pero tengo que decir que, en general, lo que está tratando de hacer no es la mejor práctica. Por favor, lea un poco en los diccionarios de Python.


Solución alternativa:

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

Y, de hecho, puedes evitar todo esto si solo usas una matriz para contener todos tus errores.

Puede cargar ambas cadenas json en los diccionarios de Python y luego combinarlas. Esto solo funcionará si hay claves únicas en cada cadena json.

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

A partir de Python 3.5, puedes combinar dos dictados con:

 merged = {**dictA, **dictB} 

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

Asi que:

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

etc.

La fusión de objetos json es bastante sencilla, pero tiene algunos casos de borde cuando se trata de colisiones clave. Los problemas más importantes tienen que ver con que un objeto tenga un valor de un tipo simple y el otro que tenga un tipo complejo (Array o Object). Tienes que decidir cómo quieres implementar eso. Nuestra elección cuando implementamos esto para json pasó a chef-solo fue fusionar Objetos y utilizar el valor del Objeto de primera fuente en todos los demás casos.

Esta fue nuestra solución:

 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 

Puede agregar otro caso después del primer caso para verificar las listas si también desea combinarlas, o para casos específicos cuando se encuentran claves especiales.

¿Qué quieres decir con la fusión? Los objetos JSON son estructuras de datos clave-valor. ¿Cuál sería una clave y un valor en este caso? Creo que necesitas crear un nuevo directorio y llenarlo con datos antiguos:

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

El método de fusión obviamente depende de usted.