Tengo un archivo de salida json y estoy tratando de cifrar un valor de clave (nombre) en él usando el método de cifrado sha256. Tengo dos apariciones de nombre en una lista de dict, pero cada vez que escribo, los cambios se reflejan una vez. ¿Alguien puede decirme dónde me falta?

Json structure:
Output.json
{
    "site": [
        {
            "name": "google", 
            "description": "Hi I am google"
        }, 
        {
            "name": "microsoft", 
            "description": "Hi, I am microsoft"
        }
    ],
    "veg": [
        {
            "status": "ok",
            "slot": null
        },
        {
            "status": "ok"
        }
    ]
}

Código:

import hashlib
import json

class test():
    def __init__(self):
    
    def encrypt(self):
        with open("Output.json", "r+") as json_file:
            res = json.load(json_file)
            for i in res['site']:
                for key,val in i.iteritems():
                    if 'name' in key:
                        hs = hashlib.sha256(val.encode('utf-8')).hexdigest()
                        res['site'][0]['name'] = hs
                        json_file.seek(0)
                        json_file.write(json.dumps(res,indent=4))
                        json_file.truncate()
                        

Salida actual.json

{
    "site": [
        {
            "name": "bbdefa2950f49882f295b1285d4fa9dec45fc4144bfb07ee6acc68762d12c2e3", 
            "description": "Hi I am google"
        }, 
        {
            "name": "microsoft", 
            "description": "Hi, I am microsoft"
        }
    ],
    "veg": [
        {
            "status": "ok",
            "slot": null
        },
        {
            "status": "ok"
        }
    ]
}
0
Aditya ray 21 ene. 2021 a las 17:03

1 respuesta

La mejor respuesta

Creo que tu problema está en esta línea:

res['site'][0]['name'] = hs

Siempre está cambiando el campo name del primer mapa en la lista site. Creo que quieres que esto sea:

i['name'] = hs

Para que esté actualizando el mapa en el que está trabajando actualmente (señalado por i).

En lugar de iterar sobre cada elemento del diccionario, puede hacer uso del hecho de que los diccionarios están hechos para buscar valores por clave y hacer esto:

if 'name' in i:
    val = i['name']
    hs = hashlib.sha256(val.encode('utf-8')).hexdigest()
    i['name'] = hs
    json_file.seek(0)
    json_file.write(json.dumps(res, indent=4))
    json_file.truncate()

En lugar de esto:

for key,val in i.iteritems():
    if 'name' in key:
        ...

Además, iteritems() debería ser items() y if 'name' in key debería ser if key == 'name', ya que key es una cadena. Tal como está, estaría haciendo coincidir cualquier entrada con un nombre de clave que contenga la subcadena 'nombre'.

ACTUALIZACIÓN: Noté que está escribiendo el archivo completo varias veces, una por cada entrada name que encripta. Incluso sin esto, le recomendaría que abra el archivo dos veces ... una para leer y otra para escribir. Esto es preferible a abrir un archivo para leer y escribir, y tener que buscar y truncar. Entonces, aquí están todos mis cambios sugeridos, junto con algunos otros ajustes, en una versión completa de su código:

import hashlib
import json

class Test:

    def encrypt(self, infile, outfile=None):
        if outfile is None:
            outfile = infile
        with open(infile) as json_file:
            res = json.load(json_file)
        for i in res['site']:
            if 'name' in i:
                i['name'] = hashlib.sha256(i['name'].encode('utf-8')).hexdigest()
        with open(outfile, "w") as json_file:
            json.dump(res, json_file, indent=4)

Test().encrypt("/tmp/input.json", "/tmp/output.json")

# Test().encrypt("/tmp/Output.json")  # <- this form will read and write to the same file

Contenido del archivo resultante:

{
    "site": [
        {
            "name": "bbdefa2950f49882f295b1285d4fa9dec45fc4144bfb07ee6acc68762d12c2e3",
            "description": "Hi I am google"
        },
        {
            "name": "9fbf261b62c1d7c00db73afb81dd97fdf20b3442e36e338cb9359b856a03bdc8",
            "description": "Hi, I am microsoft"
        }
    ],
    "veg": [
        {
            "status": "ok",
            "slot": null
        },
        {
            "status": "ok"
        }
    ]
}
1
CryptoFool 22 ene. 2021 a las 06:10