Skip to content

S5: JSON

Juan Gonzalez-Gomez edited this page Mar 7, 2022 · 4 revisions

Sesión 5: JSON

  • Tiempo: 2h (50 + 50min)
  • Fecha: Lunes, 28-Febrero-2022
  • Objetivos de la sesión:
    • Aprender el formato JSON
    • Saber cómo se intercambian datos entre cliente y servidor
    • Manejo de JSON desde VSCode

Contenido

Introducción

El formato JSON es una forma sencilla de estructurar los datos y de intercambiarlos entre aplicaciones. Aprenderemos más sobre este formato y cómo usarlo desde nuestros programas en node.js

HTTP: Páginas web y datos

El protocolo HTTP nació para servir páginas web, que están pensadas para que las lean los humanos. Cuando el navegador accede a una página web se transfieren del servidor al cliente ficheros html, ficheros css, ficheros js e imágenes fundamentalmente

Sin embargo, HTTP también se usa para que las aplicaciones intercambien datos con el servidor. Así, los servidores atienden tanto peticiones para humanos (páginas web) como peticiones para aplicaciones (servicios web)

El intercambio de datos entre las aplicaciones y el servidor se realiza mediante formatos que permiten estructurar estos datos, como XML o JSON. Recordemos que el protocolo HTTP intercambia mensajes de texto. Tanto XML como JSON utilizan texto

Ejemplos de acceso a datos

Vamos a ver algunos ejemplos de acceso a los datos ofrecidos por los servidores. A través de la URL se indica a qué información se quiere acceder y se pasan parámetros. Esta interfaz de acceso a los datos que ofrecen los servidores se denominan servicios web (web services)

Accediendo a mis datos en Github

Vamos a acceder a nuestros datos en Github. Por un lado podemos acceder a ellos como Humanos, a través de la página web de usuario. En mi caso es a través de esta URL: https://github.com/Obijuan

La URL para acceder directamente a los datos es esta: https://api.github.com/users/Obijuan. Como ejemplo hacemos una petición con curl

$ curl https://api.github.com/users/Obijuan

Y esto es lo que obtenemos:

{
  "login": "Obijuan",
  "id": 1286062,
  "node_id": "MDQ6VXNlcjEyODYwNjI=",
  "avatar_url": "https://avatars.githubusercontent.com/u/1286062?v=4",
  "gravatar_id": "",
  "url": "https://api.github.com/users/Obijuan",
  "html_url": "https://github.com/Obijuan",
  "followers_url": "https://api.github.com/users/Obijuan/followers",
  "following_url": "https://api.github.com/users/Obijuan/following{/other_user}",
  "gists_url": "https://api.github.com/users/Obijuan/gists{/gist_id}",
  "starred_url": "https://api.github.com/users/Obijuan/starred{/owner}{/repo}",
  "subscriptions_url": "https://api.github.com/users/Obijuan/subscriptions",
  "organizations_url": "https://api.github.com/users/Obijuan/orgs",
  "repos_url": "https://api.github.com/users/Obijuan/repos",
  "events_url": "https://api.github.com/users/Obijuan/events{/privacy}",
  "received_events_url": "https://api.github.com/users/Obijuan/received_events",
  "type": "User",
  "site_admin": false,
  "name": "Juan Gonzalez-Gomez",
  "company": "URJC",
  "blog": "http://www.iearobotics.com",
  "location": "Madrid (Spain)",
  "email": null,
  "hireable": null,
  "bio": "Hola!Soy Obijuan! I'm an assitant professor at the Engineering school of the  URJC University.  I really believe in the opensource spirit of sharing information",
  "twitter_username": "Obijuan_cube",
  "public_repos": 132,
  "public_gists": 1,
  "followers": 1190,
  "following": 13,
  "created_at": "2011-12-26T10:55:43Z",
  "updated_at": "2021-03-09T06:20:51Z"
}

El servidor nos ha devuelto los datos en formato JSON. Si examinamos las cabeceras del mensaje de respuesta, en el campo Content-Type vemos que el tipo es application/json

Esto mismo lo podemos hacer desde el navegador. El firefox tiene un modo que permite ver los datos JSON recibidos. Si escribimos la URL de acceso a los datos obtendremos lo siguiente:

¡¡ESTO NO ES UNA PÁGINA WEB!! Es un modo resaltado que tiene Firefox para ver los ficheros JSON devueltos por el servidor. Si pinchamos en la pestaña Raw Data veremos el fichero JSON en crudo:

También podemos acceder a las cabeceras los mensajes HTTP intercambiados, pinchando en la pestaña Headers. Ahí vemos que efectivamente hemos recibido datos en formato JSON

Puedes encontrar más información sobre la API de Github en este enlace: https://docs.github.com/en/rest

Accediendo a información meteorológica

Existen servidores que recopilan datos sobre el tiempo y ofrecen servicios web para que nuestras aplicaciones los puedan utilizar (Por ejemplo en los teléfonos móviles). Uno de estos servidores es https://www.metaweather.com/

Si nos conectamos, por defecto aparecerá una página web con el tiempo de tu zona, y la previsión para los próximos 5 días

Sin embargo, si nos conectamos a esta URL: https://www.metaweather.com/api/location/766273/ obtenemos directamente los datos en JSON. El número 766273 se corresponde con el identificador WOEID de Madrid

Si pinchamos en el botón superior de Collapse All se ven los campos principales

Genoma humano

El Proyecto Ensembl contiene el gnome completo de varios vertebrados, incluidos los humanos. Accediendo a sus páginas web se pueden hacer búsquedas de los genes. Por ejemplo, en esta captura se muestran la página con información sobre el gen humano FRAT1

Ensembl tiene una enorme base de datos con muchísima información a la que se puede acceder vía páginas web (para humanos) o bien hacer búsquedas a través de sus web services (aplicaciones). Aquí puedes encontrar la API completa, que es pública

Este es un ejemplo de petición, en el que se obtienen las 100 primeras bases del cromosoma humano FRAT1, cuyo identificador es ENSG00000165879. La información se solicita en formato JSON mediante el parámetro content-type=application/json. Con el parámetro end=100 se indica que sólo se quieren ver las 100 primeras bases del cromosoma

https://rest.ensembl.org/sequence/id/ENSG00000165879?content-type=application/json;end=100

Otros servicios

Mucha gente en internet tiene pequeños servidores que ofrecen servicios. La mayoría de ellos son simples experimentos que han hecho para aprender. Algunos de estos servicios son muy útiles para aprender a hacer tus propias aplicaciones que acceden a información remota

El formato JSON

JSON es un formato ligero para el intercambio de datos entre aplicaciones. Tiene dos ventajas fundamentales:

  • Es sencillo y legible por humanos
  • Es fácil para las máquinas generarlo y analizarlo

Todos los detalles de su gramática se encuentran en la web oficial de JSON

Estas son algunas de sus características:

  • Codificación UTF-8 por defecto. No se especifica explícitamente en el fichero
  • Su notación es un subconjunto de ECMAScript para los objetos literales. Por ello es especialmente fácil trabajar con JSON desde Javascript
  • Tipo MIME: application/json
  • Integrado en casi todos los lenguajes de programación

Elementos de JSON

Dado que JSON está pensado para ser un valor pasado como parámetro a una función o bien el valor devuelto por una función, el archivo json está formado por UN UNICO ELEMENTO. Este elemento puede ser bien un Elemento simple o un elemento compuesto (formado por otros elementos)

Elementos simples

Son 5 tipos: null, true, false, Cadenas y números

  • null: Es el valor estándar usado para indicar que no hay valor
null
  • true: Valor estándar para indicar que algo es verdadero o que está activado
true
  • false: Valor estándar para indicar que algo es falso o que no está activado
false
  • Cadenas: Cualquier valor situado entre comillas. Se usa el carácter '' como secuencia de escape para dotar de significado especial a los siguientes caracteres:
    • \\: Carácter ''
    • \/: Carácter '/'
    • \b: Retroceso (Backspace)
    • \n: Salto de linea (LF)
    • '\r`: Salto de carro (CR)
    • \t: Tabulador (TAB)
    • \uxxxx: Numero hexadecimal. Donde x son dígitos hexadecimales: \u01ab

Ejemplo de fichero json con una cadena

"Esta es una cadena valida\n"
  • Números: Expresados en base 10 (decimal). Ej: 3424, -34. Con parte entera y decimales: 3.1415 ó en notación científica: 3e8
3.1415

Elementos compuestos

Son elementos que contienen otros elmentos a su vez (tanto simples como compuestos)

  • Objeto: Contiene una colección de pares Nombre/valor. El nombre SIEMPE va entrecomillado ("), igual que las cadenas. El valor puede ser cualquiera de los elementos conocidos (simples o compuestos)

Todos estos son ejemplos de ficheros json válidos, que contienen 1 objeto:

Objeto vacio

{}

Objeto con dos propiedades: x, y

{ "x":5, "y": 6 }

Objeto con otro objeto dentro

{
    "nombre": "bola",
    "posicion": {
        "x": 5.3,
        "y": 2.0
    }
}
  • Array: Una lista ordenada de elementos (que pueden ser simples o compuestos a su vez)

Arrray vacio

[]

Array con dos elementos

[ 534.3, "null"]

Array con varios elementos

[ 3, "true", "hola", {"a":2, "b": "false"}]

Array con arrays

[ [1,2], ["hola", ":-)"]]

JSON y VSCode

El VSCode hace el análisis sintáctico de los ficheros json sobre la marcha, por lo que resulta muy útil. En este pantallazo vemos un ejemplo de un fichero json que contiene un objecto con las propiedades nombre y posición. Esta última es a su vez otro objeto

En la pestaña de OUTLINE vemos su estructura. Sabemos que es un fichero bien formado porque no hay elementos en rojo en esta estructura. Si ahora cometemos un error, lo que aparece es esto:

En el editor está resaltado en rojo la propiedad x. Si ponemos el cursos encima nos indica la causa del error: Las propiedades deben estar siempre entre comillas. También vemos en la parte del esquema (OUTLINE) que hay elementos en rojo: hay errores

JSON y XML

JSON y XML son ambos lenguajes para definir una estructura en los datos. Como ejemplo de comparación usaremos el ejemplo del elemento tienda, que contiene productos

Este es el archivo en XML: (Se ha omitido la gramática de definición del lenguaje)

<?xml version="1.0" encoding="UTF-8"?>

<tienda>
    <producto>
        <nombre>Alhambra II</nombre>
        <descripcion>Placa con FPGA ice40HX8K</descripcion>
        <stock>3</stock>
    </producto>

    <producto>
        <nombre>Icestick</nombre>
        <stock>10</stock>
    </producto>
</tienda>

Y este es el archivo JSON:

[
  {
    "nombre": "Alhambra II",
    "descripción": "Placa con FPGA ice40HX8K",
    "stock": 3
  },
  {
    "nombre": "Icestick",
    "stock": 10
  }
]

Si los ponemos en paralelo se comparan mejor. La relación es prácticamente uno a uno

Las principales diferencias son:

  • XML es más "verboso"
  • En XML hay que definir la codificación (En Json es UTF-8 por defecto)
  • XML permite validar los datos contra una gramática (pero JSON no)

JSON y Javascript

El formato JSON es un subconjunto de la forma en la que se crean objetos literales en Javascript. Veremos ejemplos de creación de objetos literales directamente en javascript y luego leyéndolos de un fichero .json

Ejemplo 1: Elemento tienda

Creamos el elemento tienda que contiene dos productos. Luego recorremos la estructura y mostrarmos en la consola información:

//-- Crear la variable tienda, que es una estructura formada
//-- por dos productos
const tienda = [
  {
    nombre: "Alhambra II",
    descripcion: "Placa con FPGA ice40HX8K",
    stock: 3
  },
  {
    nombre: "Icestick",
    stock: 10
  }
];

//-- Mostrar informacion sobre la tienda
console.log("Productos en la tienda: " + tienda.length);

//-- Recorrer el array de productos
tienda.forEach((element, index)=>{
  console.log("Producto: " + (index + 1) + ": " + element.nombre);
});

Al ejecutarlo obtenemos este resultado:

$ node Ej-01-tienda-literal.js 
Productos en la tienda: 2
Producto: 1: Alhambra II
Producto: 2: Icestick

Conversión de JSON a variables Javascript

Para obtener una variable a partir de un texto en JSON utilizamos el método JSON.parse(cadena)

Ejemplo 2: Elemento tienda en formato JSON en una cadena

En este ejemplo definimos la misma estructura de la tienda pero en formato JSON, almacenado en una cadena. La diferencia está en que en la cadena JSON los nombres de las propiedades de los objetos se deben poner entre comillas

Para acceder al nombre de los productos se puede utilizar bien la notación con punto: element.nombre o bien la notación de corchetes: element["nombre"]

El funcionamiento del ejemplo es el mismo que el anterior

//-- Cadena con la estructura de la tienda en JSON
const tienda_json = `[
  {
    "nombre": "Alhambra II",
    "descripcion": "Placa con FPGA ice40HX8K",
    "stock": 3
  },
  {
    "nombre": "Icestick",
    "stock": 10
  }
]`

//-- Crear la estructura tienda a partir de la cadena en json
const tienda = JSON.parse(tienda_json);

//-- Mostrar informacion sobre la tienda
console.log("Productos en la tienda: " + tienda.length);

//-- Recorrer el array de productos
tienda.forEach((element, index)=>{
  console.log("Producto: " + (index + 1) + ": " + element["nombre"]);
});

Ejemplo 3: Elemento tienda en formato JSON en un fichero

Este es el mismo ejemplo pero ahora la cadena JSON se lee directamente de este fichero:

Fichero: Ej-03-tienda-json-fich.json:

[
    {
      "nombre": "Alhambra II",
      "descripcion": "Placa con FPGA ice40HX8K",
      "stock": 3
    },
    {
      "nombre": "Icestick",
      "stock": 10
    }
]

Desde el programa en javascript se lee este fichero y se crea la variable tienda con esta estructura

//-- Crear una variable con la estructura definida
//-- en un fichero JSON

const fs = require('fs');

//-- Npmbre del fichero JSON a leer
const FICHERO_JSON = "Ej-03-tienda-json-fich.json"

//-- Leer el fichero JSON
const  tienda_json = fs.readFileSync(FICHERO_JSON);

//-- Crear la estructura tienda a partir del contenido del fichero
const tienda = JSON.parse(tienda_json);

//-- Mostrar informacion sobre la tienda
console.log("Productos en la tienda: " + tienda.length);

//-- Recorrer el array de productos
tienda.forEach((element, index)=>{
  console.log("Producto: " + (index + 1) + ": " + element["nombre"]);
});

Conversión de variable a formato JSON

También podemos hacer la operación inversa: pasar una variable a formato JSON. Se hace con el método: JSON.stringify(variable)

Ejemplo 4: Modificación de la tienda y escritura a un fichero

En este ejemplo leemos el mismo fichero JSON de entrada del ejemplo 3, modificamos el nombre del producto 2 a Icesbreaker, y guardamos la nueva información en el fichero Ej-04-tienda-modificacion.js

//-- Lectura y modificación de un fichero JSON
const fs = require('fs');

//-- Npmbre del fichero JSON a leer
const FICHERO_JSON = "Ej-03-tienda-json-fich.json"

//-- NOmbre del fichero JSON de salida
const FICHERO_JSON_OUT = "Ej-04-tienda-modificacion.json"

//-- Leer el fichero JSON
const  tienda_json = fs.readFileSync(FICHERO_JSON);

//-- Crear la estructura tienda a partir del contenido del fichero
const tienda = JSON.parse(tienda_json);

//-- Modificar el nombre del producto 2
tienda[1]["nombre"] = "IceBeraker"

//-- Mostrar informacion sobre la tienda
console.log("Productos en la tienda: " + tienda.length);

//-- Recorrer el array de productos
tienda.forEach((element, index)=>{
  console.log("Producto: " + (index + 1) + ": " + element["nombre"]);
});

//-- Convertir la variable a cadena JSON
let myJSON = JSON.stringify(tienda);

//-- Guardarla en el fichero destino
fs.writeFileSync(FICHERO_JSON_OUT, myJSON);

console.log("Información guardada en fichero: " + FICHERO_JSON_OUT);

Clientes JSON

Los clientes HTTP se crean muy fácilmente en nodo, usando el módulo http/https. Esto nos permite crear scripts muy fácilmente para obtener datos de los servidores. Para realizar una petición GET basta con usar el método: https.get(URL, callback)

Ejemplo 5: Cliente para obtener la temperatura de madrid

El siguiente programa es un cliente que se conecta a la URL de metaweather que vimos en la sección Accediendo a la información meteorológica

Los datos recibidos, si la petición es correcta, se reciben por el stream de entrada y se van almacenando en la variable data. Cuando se ha terminado de recibir todos los datos convierte a variable y se accede a los campos de la estructura para obtener el lugar, la temperatura y la hora:

const https = require('https');

const ENDPOINT = "https://www.metaweather.com/api/location/766273/";

let request = https.get(ENDPOINT, (res) => { 
    if (res.statusCode !== 200 ) {
        console.error("Error");
        console.log("Código de respuesta: " + res.statusCode);
        res.resume();
        return;
    }

    let data = '';

    res.on('data', (chunk) => {
        data += chunk;
    });

    res.on('close', () => {
        console.log('Datos recibidos');

        //-- Obtener la variable con la informacion
        let tiempo = JSON.parse(data);

        let temp = tiempo.consolidated_weather[0].the_temp;

        console.log("Lugar: " + tiempo.title);
        console.log("Temperatura: " + temp);
        console.log("Hora: " + tiempo.time);
        
    });
   
});

Autor

Licencia

Enlaces

TEORIA

Soluciones

LABORATORIO

Prácticas y sesiones de laboratorio

Práctica 0: Herramientas

Práctica 1: Node.js: Tienda Básica

Práctica 2: Interacción cliente-servidor. Tienda mejorada

Práctica 3: Websockets: Chat

Practica 4: Electron: Home Chat

  • L11: Home chat (26-Abril-2022)
  • L12: Laboratorio puro. NO hay contenido nuevo (9-Mayo-2022)
  • L13: Laboratorio/Tutorias. No hay contenido nuevo (10-Mayo-2022)

EXAMENES

Curso 2020-2021

Clone this wiki locally