El analizador Python json permite claves duplicadas
duplicates key (2)
Muchas gracias @Lukas Graf, también lo hice funcionar implementando mi propia versión de la función de enlace
def dict_raise_on_duplicates(ordered_pairs):
count=0
d=collections.OrderedDict()
for k,v in ordered_pairs:
if k in d:
d[k+''_dupl_''+str(count)]=v
count+=1
else:
d[k]=v
return d
Lo único que queda es deshacerse automáticamente de los corchetes dobles y he terminado: D Gracias de nuevo
Necesito analizar un archivo json que desafortunadamente para mí no sigue el prototipo. Tengo dos problemas con los datos, pero ya he encontrado una solución para ellos, así que solo los mencionaré al final, tal vez alguien pueda ayudarme allí también.
Entonces necesito analizar entradas como esta:
"Test":{
"entry":{
"Type":"Something"
},
"entry":{
"Type":"Something_Else"
}
}, ...
El analizador predeterminado json actualiza el diccionario y, por lo tanto, usa solo la última entrada. Tengo que almacenar de alguna manera el otro también, y no tengo idea de cómo hacerlo. También TENGO que almacenar las claves en varios diccionarios en el mismo orden en que aparecen en el archivo, por eso estoy usando un OrderedDict para hacerlo. funciona bien, así que si hay alguna forma de expandir esto con las entradas duplicadas, estaría agradecido.
Mi segundo problema es que este mismo archivo json contiene entradas como esa:
"Test":{
{
"Type":"Something"
}
}
La función Json.load () genera una excepción cuando llega a esa línea en el archivo json. La única forma en que pude solucionar esto fue eliminar manualmente los soportes internos.
Gracias por adelantado
Puede usar
JSONDecoder.object_pairs_hook
para personalizar cómo
JSONDecoder
decodifica objetos.
A esta función de enlace se le pasará una lista de pares
(key, value)
que generalmente realiza algún procesamiento y luego se convertirá en una
dict
.
Sin embargo, dado que los diccionarios Python no permiten claves duplicadas (y simplemente no puede cambiar eso), puede devolver los pares sin cambios en el gancho y obtener una lista anidada de pares
(key, value)
cuando decodifica su JSON:
from json import JSONDecoder
def parse_object_pairs(pairs):
return pairs
data = """
{"foo": {"baz": 42}, "foo": 7}
"""
decoder = JSONDecoder(object_pairs_hook=parse_object_pairs)
obj = decoder.decode(data)
print obj
Salida:
[(u''foo'', [(u''baz'', 42)]), (u''foo'', 7)]
La forma en que use esta estructura de datos depende de usted.
Como se indicó anteriormente, los diccionarios de Python no permitirán claves duplicadas, y no hay forma de evitarlo.
¿Cómo harías una búsqueda basada en una clave?
dct[key]
sería ambiguo.
Por lo tanto, puede implementar su propia lógica para manejar una búsqueda de la manera en que espera que funcione, o implementar algún tipo de evitación de colisión para hacer que las claves sean únicas si no lo son, y luego crear un diccionario a partir de su lista anidada.
Editar : como dijo que le gustaría modificar la clave duplicada para que sea única, así es como lo haría:
from collections import OrderedDict
from json import JSONDecoder
def make_unique(key, dct):
counter = 0
unique_key = key
while unique_key in dct:
counter += 1
unique_key = ''{}_{}''.format(key, counter)
return unique_key
def parse_object_pairs(pairs):
dct = OrderedDict()
for key, value in pairs:
if key in dct:
key = make_unique(key, dct)
dct[key] = value
return dct
data = """
{"foo": {"baz": 42, "baz": 77}, "foo": 7, "foo": 23}
"""
decoder = JSONDecoder(object_pairs_hook=parse_object_pairs)
obj = decoder.decode(data)
print obj
Salida:
OrderedDict([(u''foo'', OrderedDict([(u''baz'', 42), (''baz_1'', 77)])), (''foo_1'', 7), (''foo_2'', 23)])
La función
make_unique
es responsable de devolver una clave libre de colisión.
En este ejemplo, solo sufija la clave con
_n
donde
n
es un contador incremental, solo adáptelo a sus necesidades.
Debido a que
object_pairs_hook
recibe los pares exactamente en el orden en que aparecen en el documento JSON, también es posible preservar ese orden utilizando un
OrderedDict
, también lo
OrderedDict
.