Codificación y decodificación de objetos personalizados en Python-JSON

JSON , como sabemos, significa Notación de objetos de JavaScript . Es un formato ligero de intercambio de datos y se ha convertido en el medio más popular de intercambio de datos en la web. La razón detrás de su popularidad es que es legible por humanos y fácil de analizar y generar para las máquinas. Además, es el formato más utilizado para las API REST.

Nota: Para obtener más información, consulte Lectura, escritura y análisis de JSON mediante Python .

Empezando

Python proporciona una jsonbiblioteca integrada para manejar objetos JSON. Todo lo que necesita es importar el módulo JSON usando la siguiente línea en su programa Python y comenzar a usar su funcionalidad.

import json

Ahora, el módulo JSON proporciona una gran cantidad de funciones y vamos a analizar solo 2 métodos de ellos. Son vertederos y cargas . El proceso de convertir un objeto python en uno json se denomina serialización o codificación JSON y el proceso inverso, es decir, convertir un objeto json en uno Python, se denomina deserialización o decodificación.

Para codificar, usamos json.dumps()y para decodificar, usaremos json.loads(). Por lo tanto, es obvio que el método dumps convertirá un objeto python en una string JSON serializada y el método loads analizará el objeto Python a partir de una string JSON serializada.

Nota:

  • Vale la pena mencionar aquí que el objeto JSON que se crea durante la serialización es solo una string de Python, es por eso que encontrará los términos «objeto JSON» y «string JSON» usados ​​indistintamente en este artículo.
  • También es importante tener en cuenta que un objeto JSON corresponde a un Diccionario en Python. Entonces, cuando usa el método de carga, se devuelve un diccionario de Python de forma predeterminada (a menos que cambie este comportamiento como se explica en la sección de decodificación personalizada de este artículo)

Ejemplo:

import json
  
# A basic python dictionary
py_object = {"c": 0, "b": 0, "a": 0} 
  
# Encoding
json_string = json.dumps(py_object)
print(json_string)
print(type(json_string))
  
# Decoding JSON
py_obj = json.loads(json_string) 
print()
print(py_obj)
print(type(py_obj))

Producción:

{"c": 0, "b": 0, "a": 0}
<class 'str'>

{'c': 0, 'b': 0, 'a': 0}
<class 'dict'>

Aunque lo que vimos arriba es un ejemplo muy sencillo. Pero, ¿te has preguntado qué sucede en el caso de los objetos personalizados? En ese caso, el código anterior no funcionará y obtendremos un error similar a: TypeError: Object of type SampleClass is not JSON serializable . ¿Entonces lo que hay que hacer? No se preocupe, llegaremos a la siguiente sección.

Codificación y decodificación de objetos personalizados

En tales casos, debemos esforzarnos más para que se serialicen. Veamos cómo podemos hacer eso. Supongamos que tenemos una clase Student definida por el usuario y queremos que sea JSON serializable. La forma más sencilla de hacerlo es definir un método en nuestra clase que proporcione la versión JSON de la instancia de nuestra clase.

Ejemplo:

import json
   
class Student:
    def __init__(self, name, roll_no, address):
        self.name = name
        self.roll_no = roll_no
        self.address = address
   
    def to_json(self):
        '''
        convert the instance of this class to json
        '''
        return json.dumps(self, indent = 4, default=lambda o: o.__dict__)
   
class Address:
    def __init__(self, city, street, pin):
        self.city = city
        self.street = street
        self.pin = pin
          
address = Address("Bulandshahr", "Adarsh Nagar", "203001")
student = Student("Raju", 53, address)
  
# Encoding
student_json = student.to_json()
print(student_json)
print(type(student_json))
  
# Decoding
student = json.loads(student_json)
print(student)
print(type(student))

Producción:

{
«nombre»: «Raju»,
«roll_no»: 53,
«dirección»: {
«ciudad»: «Bulandshahr»,
«calle»: «Adarsh ​​Nagar»,
«pin»: «203001»
}
}
<class ‘str ‘>

{‘name’: ‘Raju’, ‘roll_no’: 53, ‘address’: {‘city’: ‘Bulandshahr’, ‘street’: ‘Adarsh ​​Nagar’, ‘pin’: ‘203001’}}
<class ‘dict ‘>

Otra forma de lograr esto es crear una nueva clase que extienda el JSONEncoder y luego usar esa clase como argumento para el método de volcados .

Ejemplo:

import json
from json import JSONEncoder
  
class Student:
    def __init__(self, name, roll_no, address):
        self.name = name
        self.roll_no = roll_no
        self.address = address
  
  
class Address:
    def __init__(self, city, street, pin):
        self.city = city
        self.street = street
        self.pin = pin
  
class EncodeStudent(JSONEncoder):
        def default(self, o):
            return o.__dict__
              
address = Address("Bulandshahr", "Adarsh Nagar", "203001")
student = Student("Raju", 53, address)
  
# Encoding custom object to json
# using cls(class) argument of
# dumps method
student_JSON = json.dumps(student, indent = 4,
                          cls = EncodeStudent)
print(student_JSON)
print(type(student_JSON))
  
# Decoding
student = json.loads(student_JSON)
print()
print(student)
print(type(student))

Producción:

{
«nombre»: «Raju»,
«roll_no»: 53,
«dirección»: {
«ciudad»: «Bulandshahr»,
«calle»: «Adarsh ​​Nagar»,
«pin»: «203001»
}
}
<class ‘str ‘>

{‘name’: ‘Raju’, ‘roll_no’: 53, ‘address’: {‘city’: ‘Bulandshahr’, ‘street’: ‘Adarsh ​​Nagar’, ‘pin’: ‘203001’}}
<class ‘dict ‘>

Para la decodificación personalizada , si queremos convertir el JSON en algún otro objeto de Python (es decir, no en el diccionario predeterminado), hay una manera muy simple de hacerlo que usa el parámetro object_hook del método de carga . Todo lo que tenemos que hacer es definir un método que definirá cómo queremos procesar los datos y luego enviar ese método como el argumento object_hook al método de carga, ver en el código dado. Además, el tipo de retorno de la carga ya no será el diccionario de Python. Cualquiera que sea el tipo de retorno del método que pasaremos como object_hook, también se convertirá en el tipo de retorno del método de carga. Esto significa que en el siguiente ejemplo, el número complejo será el tipo de retorno.

import json
  
  
def as_complex(dct):
      
    if '__complex__' in dct:
        return complex(dct['real'], dct['imag'])
      
    return dct
  
res = json.loads('{"__complex__": true, "real": 1, "imag": 2}',
           object_hook = as_complex)
print(res)
print(type(res))

Producción:

(1+2j)
<class 'complex'>

Publicación traducida automáticamente

Artículo escrito por vinayj y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *