100 - Procesar archivos con formato JSON en Python (módulo json)

Vimos en el concepto anterior como podemos acceder a recursos de Internet desde Python. Un recurso muy común para transferir datos en Internet son los archivos con formato JSON.

La Biblioteca estándar de Python cuenta con un módulo que nos facilita trabajar con archivos JSON.

Ver video

El formato JSON se lo puede transformar en Python a un diccionario. Por ejemplo:

import json

cadena="""
  {
      "codigo":"1",
      "descripcion":"papas",
      "precio":"13.45"
  }
"""
print(cadena) # imprimimos un string
diccionario=json.loads(cadena)
print(diccionario) # imprimimos un diccionario

json Python

De forma similar si disponemos de un vector, luego la transformación será a una lista con elementos de tipo diccionario:

import json

cadena="""
[ 
  {
      "codigo":"1",
      "descripcion":"papas",
      "precio":"13.45"
  },
  {
      "codigo":"2",
      "descripcion":"manzanas",
      "precio":"45"
  }  
]  
"""
print(cadena) # imprimimos un string
lista=json.loads(cadena)
print(lista) # imprimimos una lista

json Python

Problema 1

Implementar un sitio WEB en PHP que retorne un archivo con formato JSON con los datos de diferentes artículos.

Para resolver el problema debemos tener un conocimiento del lenguaje PHP y del gestor de base de datos MySQL.

Cree una base de datos llamada 'pythonya' y una tabla 'articulos' con los siguientes datos:

CREATE TABLE `articulos` (
  `codigo` int(11) NOT NULL AUTO_INCREMENT,
  `descripcion` varchar(50) DEFAULT NULL,
  `precio` float DEFAULT NULL,
  PRIMARY KEY (`codigo`)
);

insert into `articulos` values (1,'papas',15);
insert into `articulos` values (2,'manzanas',24);
insert into `articulos` values (3,'peras',45.3);
insert into `articulos` values (4,'naranjas',22);
insert into `articulos` values (5,'pomelos',29);
insert into `articulos` values (6,'frutillas',130);
insert into `articulos` values (7,'anana',75);

Seguidamente proceda a codificar el siguiente archivo PHP que se conecta a la base de datos 'pythonya', recupera todas las filas de la tabla 'articulos' y finalmente retorna todos los datos en formato JSON:

Programa: retornararticulos.php

<?php
header('Content-Type: application/json');

$server="localhost";
$usuario="root";
$clave="";
$base="pythonya";
$conexion=mysqli_connect($server,$usuario,$clave,$base) or die("problemas") ;
mysqli_set_charset($conexion,'utf8'); 

$datos = mysqli_query($conexion, "SELECT codigo, descripcion, precio from articulos");
$resultado = mysqli_fetch_all($datos, MYSQLI_ASSOC);
echo json_encode($resultado);        
?>

Si ya ha estudiado un poco de PHP sabe que al solicitar ésta página desde un navegador web lo que sucede es que retorna un archivo en formato JSON:

json Python

Ahora implementaremos una aplicación en Python que recupere y muestre los datos del archivo JSON generado en un servidor de Internet accediendo a una base de datos MySQL a través de PHP:

Programa: ejercicio340.py

from urllib import request
import json

pagina=request.urlopen("http://localhost/pythonya/retornararticulos.php")
datos=pagina.read().decode("utf-8")
print(datos) # imprimimos un string
print("_"*100)
lista=json.loads(datos) # convertimos el string a una lista
print(lista) # imprimimos una lista
print("_"*100)
for elemento in lista:
    print(f"{elemento['codigo']}  {elemento['descripcion']:50}  {elemento['precio']:>12}")

El resultado de ejecutar la aplicación (recuerde tener activo el servidor web con PHP y MySQL):

json Python

Importamos los módulos request y json:

from urllib import request
import json

Solicitamos al servidor local (localhost) el recurso 'retornararticulos.php' localizado en la carpeta 'pythonya':

pagina=request.urlopen("http://localhost/pythonya/retornararticulos.php")

Leemos y decodificamos a formato 'utf-8':

datos=pagina.read().decode("utf-8")

La variable 'datos' es un string:

print(datos) # imprimimos un string

Mediante el método 'loads' del módulo 'json' transformamos el contenido del string en una lista con elementos de tipo diccionario:

lista=json.loads(datos) # convertimos el string a una lista

Imprimimos la lista completa:

print(lista) # imprimimos una lista

Hacemos una impresión de cada elemento de la lista con un formato más legible para el usuario:

for elemento in lista:
    print(f"{elemento['codigo']}  {elemento['descripcion']:50}  {elemento['precio']:>12}")

Problema 2

Ingresar por teclado el código de un artículo, seguidamente recuperar los datos de dicho artículo del servidor local. Pasar el código del artículo como parámetro 'GET' en la llamada.

La aplicación en PHP que recupera los datos de un determinado artículo que llega como parámetro es:

Programa: retornararunarticulo.php

Ver video

<?php
header('Content-Type: application/json');

$server="localhost";
$usuario="root";
$clave="";
$base="pythonya";
$conexion=mysqli_connect($server,$usuario,$clave,$base) or die("problemas") ;
mysqli_set_charset($conexion,'utf8'); 

$datos = mysqli_query($conexion, "SELECT codigo, descripcion, precio from articulos where codigo=$_GET[codigo]");
$resultado = mysqli_fetch_all($datos, MYSQLI_ASSOC);
echo json_encode($resultado);        
?>

Es importante notar que ahora recuperamos solo una fila de la tabla 'articulos', es decir aquel que coincide con el código de artículo pasado en la llamada:

$datos = mysqli_query($conexion, "SELECT codigo, descripcion, precio from articulos where codigo=$_GET[codigo]");

Ahora veamos el programa Python que llama a la página PHP anterior.

Programa: ejercicio341.py

from urllib import request
import json

codigo=input("Ingrese el código de artículo a consultar:")
pagina=request.urlopen(f"http://localhost/pythonya/retornarunarticulo.php?codigo={codigo}")
datos=pagina.read().decode("utf-8")
lista=json.loads(datos)
if len(lista)>0:
    print(f"Descripción:{lista[0]['descripcion']}")
    print(f"Precio:{lista[0]['precio']}")
else:
    print("No existe un artículo con el código ingresado")

El resultado de ejecutar la aplicación y cargar un código de artículo a consultar (recuerde tener activo el servidor web con PHP y MySQL):

json Python

Cuando nos conectamos al servidor le pasamos un parámetro llamado código y un número que ingresamos previamente por teclado:

codigo=input("Ingrese el código de artículo a consultar:")
pagina=request.urlopen(f"http://localhost/pythonya/retornarunarticulo.php?codigo={codigo}")

Una vez que recuperamos los datos del servidor procedemos a convertir el string devuelto:

lista=json.loads(datos)

Si la lista no está vacía procedemos a mostrar la descripción y precio del artículo consultado:

if len(lista)>0:
    print(f"Descripción:{lista[0]['descripcion']}")
    print(f"Precio:{lista[0]['precio']}")

En caso contrario significa que intentamos consultar un código de artículo inexistente:

else:
    print("No existe un artículo con el código ingresado")

Problemas propuestos

  • Confeccionar una aplicación visual con tkinter que permita mostrar todos los artículos. Recuperar del servidor web llamando al recurso 'retornararticulos.php'.

    Disponer dos botones para poder navegar entre los distintos registros recuperados.

    La interfaz visual debe ser similar a:

    json python

    Ver video

  • El sitio web

    https://jsonplaceholder.typicode.com/
    

    se puede utilizar para recuperar datos con diferentes formatos (JSON por ejemplo) y probar nuestros algoritmos.

    Confeccionar una aplicación en Python que recupere el archivo JSON de la siguiente dirección web:

    https://jsonplaceholder.typicode.com/posts
    

    Nos retorna un archivo JSON con un formato similar a:

    [
      {
        "userId": 1,
        "id": 1,
        "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
        "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit
                 molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
      },
      {
        "userId": 1,
        "id": 2,
        "title": "qui est esse",
        "body": "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores 
                 neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui 
                 aperiam non debitis possimus qui neque nisi nulla"
      }]
    

    Convertir los datos recuperados a una lista y mediante un for mostrar los atributos "userID", "id", "title" y "body".

    Ver video

  • Hacer la misma actividad que el problema anterior con el recurso que devuelve la dirección:

    https://jsonplaceholder.typicode.com/users
    

    Nos retorna un archivo JSON con un formato similar a:

    [
      {
        "id": 1,
        "name": "Leanne Graham",
        "username": "Bret",
        "email": "Sincere@april.biz",
        "address": {
          "street": "Kulas Light",
          "suite": "Apt. 556",
          "city": "Gwenborough",
          "zipcode": "92998-3874",
          "geo": {
            "lat": "-37.3159",
            "lng": "81.1496"
          }
        },
        "phone": "1-770-736-8031 x56442",
        "website": "hildegard.org",
        "company": {
          "name": "Romaguera-Crona",
          "catchPhrase": "Multi-layered client-server neural-net",
          "bs": "harness real-time e-markets"
        }
      },
      {
        "id": 2,
        "name": "Ervin Howell",
        "username": "Antonette",
        "email": "Shanna@melissa.tv",
        "address": {
          "street": "Victor Plains",
          "suite": "Suite 879",
          "city": "Wisokyburgh",
          "zipcode": "90566-7771",
          "geo": {
            "lat": "-43.9509",
            "lng": "-34.4618"
          }
        },
        "phone": "010-692-6593 x09125",
        "website": "anastasia.net",
        "company": {
          "name": "Deckow-Crist",
          "catchPhrase": "Proactive didactic contingency",
          "bs": "synergize scalable supply-chains"
        }
      }
    ]
    

    Convertir los datos recuperados a una lista y mediante un for mostrar todos los atributos.

    Ver video

Solución
ejercicio342.py


from urllib import request
import json
import tkinter as tk
from tkinter import ttk

class Aplicacion:
    def __init__(self):
        self.ventana1=tk.Tk()
        self.label1=ttk.Label(text="Código:", width=25)
        self.label1.grid(column=0, row=0, padx=10, pady=10)
        self.label2=ttk.Label(text="", width=25)
        self.label2.grid(column=1, row=0, padx=10, pady=10)
        
        self.label3=ttk.Label(text="Descripción:", width=25)
        self.label3.grid(column=0, row=1, padx=10, pady=10)
        self.label4=ttk.Label(text="", width=25)
        self.label4.grid(column=1, row=1, padx=10, pady=10)

        self.label5=ttk.Label(text="Precio:", width=25)
        self.label5.grid(column=0, row=2, padx=10, pady=10)
        self.label6=ttk.Label(text="", width=25)
        self.label6.grid(column=1, row=2, padx=10, pady=10)

        self.boton1=ttk.Button(self.ventana1, text="Anterior", command=self.anterior, width=25)
        self.boton1.grid(column=0, row=3, padx=10, pady=10)
        self.boton2=ttk.Button(self.ventana1, text="Siguiente", command=self.siguiente, width=25)
        self.boton2.grid(column=1, row=3, padx=10, pady=10)
        self.articulos=[]
        self.recuperar_articulos()
        self.indice=0
        self.mostrar_articulo()
        self.ventana1.mainloop()

    def anterior(self):
        if self.indice>0:
            self.indice-=1
            self.mostrar_articulo()

    def siguiente(self):
        if self.indice<len(self.articulos)-1:
            self.indice+=1
            self.mostrar_articulo()

    def recuperar_articulos(self):
        pagina=request.urlopen("http://localhost/pythonya/retornararticulos.php")
        datos=pagina.read().decode("utf-8")
        self.articulos=json.loads(datos)

    def mostrar_articulo(self):
        if len(self.articulos)>0:
            self.label2.config(text=self.articulos[self.indice]['codigo'])
            self.label4.config(text=self.articulos[self.indice]['descripcion'])
            self.label6.config(text=self.articulos[self.indice]['precio'])

aplicacion1=Aplicacion()




ejercicio343.py


from urllib import request
import json

pagina=request.urlopen("https://jsonplaceholder.typicode.com/posts")
datos=pagina.read().decode("utf-8")
lista=json.loads(datos)
for elemento in lista:
    print("userId:",elemento['userId'])
    print("Id:",elemento['id'])
    print("title:",elemento['title'])
    print("body:",elemento['body'])
    print("_"*80)




ejercicio344.py


from urllib import request
import json

pagina=request.urlopen("https://jsonplaceholder.typicode.com/users")
datos=pagina.read().decode("utf-8")
lista=json.loads(datos)
print(lista)
for elemento in lista:   
    print("id:",elemento['id'])
    print("name:",elemento['name'])
    print("username:",elemento['username'])
    print("email:",elemento['email'])
    print("street:",elemento["address"]["street"])
    print("suite:",elemento["address"]["suite"])    
    print("city:",elemento["address"]["city"])
    print("zipcode:",elemento["address"]["zipcode"])
    print("lat:",elemento["address"]["geo"]["lat"])
    print("lng:",elemento["address"]["geo"]["lng"])
    print("phone:",elemento['phone'])
    print("website:",elemento['website'])
    print("company name:",elemento["company"]["name"])
    print("catchPhrase:",elemento["company"]["catchPhrase"])
    print("bs:",elemento["company"]["bs"])
    print("_"*80)