Ficheros JSON¶
JSON (JavaScript Object Notation) es un formato ligero de intercambio de datos. Es un fichero fácil de leer y escribir para los humanos y también fácil de analizar y generar para las máquinas. Se basa en un subconjunto del lenguaje de programación JavaScript. Debido a su amplia adopción como alternativa a XML. JSON es un formato de texto que es completamente independiente del lenguaje pero utiliza convenciones que son ampliamente conocidos por los programadores de la familia de lenguajes C, incluyendo C, C++, C#, Java, JavaScript, Perl, Python, y muchos otros. Estas propiedades hacen que JSON sea un lenguaje ideal para el intercambio de datos.
JSON se utiliza hoy en día en cada API web única.
JSON se basa en dos estructuras que son universales; virtualmente todos los lenguajes de programación las soportan de una forma u otra:
- Una colección de pares de name/value. En varios lenguajes, esto se realiza como un objeto, registro, estructura, diccionario, tabla hash, lista con clave o matriz asociativa.
- Una lista ordenada de valores. En la mayoría de los lenguajes, esto se realiza como una matriz, vector, lista o secuencia.
Tipos de datos disponibles¶
- Números: Se permiten números negativos y opcionalmente pueden contener parte fraccional separada por puntos. Ejemplo: 123.456
- Cadenas: Representan secuencias de cero o más caracteres. Se ponen entre doble comilla y se permiten cadenas de escape. Ejemplo: "Hola"
- Booleanos: Representan valores booleanos y pueden tener dos valores: true y false
- null: Representan el valor nulo.
- Array: Representa una lista ordenada de cero o más valores los cuales pueden ser de cualquier tipo. Los valores se separan por comas y el vector se mete entre corchetes.
- Objetos: Son colecciones no ordenadas de pares de la forma
nombre:valor
separados por comas y puestas entre llaves. El nombre tiene que ser una cadena entre comillas dobles. El valor puede ser de cualquier tipo.
Ejemplo de fichero JSON¶
{
"departamentos": [
{
"id": 8,
"nombre": "Ventas",
"director": "Juan Rodríguez",
"empleados": [
{
"nombre": "Pedro",
"apellido": "Fernández"
},
{
"nombre": "Jacinto",
"apellido": "Benavente"
}
]
},
{
"id": 9,
"nombre": "Recursos Humanos",
"director": "María Pérez",
"empleados": [
{
"nombre": "Laura",
"apellido": "González"
},
{
"nombre": "Roberto",
"apellido": "Martínez"
}
]
},
{
"id": 10,
"nombre": "Desarrollo",
"director": "Ana García",
"empleados": [
{
"nombre": "Luis",
"apellido": "López"
},
{
"nombre": "Elena",
"apellido": "Sánchez"
}
]
}
]
}
El fichero anterior se puede traducir como un array Departamentos donde cada Departamento:
- Campos: id, director, empleados
- empleados: Array de Empleado con campos: nombre, apellido
URL oficial¶
JSON vs XML¶
Java JSON¶
Java por defecto no ofrece ninguna funcionalidad integrada para analizar o crear JSON, en lugar de eso, tendremos que confiar en una biblioteca/paquete de terceros.
En la actualidad existen varias librerías para pasar transformar un objeto Java en una cadena JSON (serialización) o viceversa (deserialización).
Desde la página en donde se encuentra la especificación de JSON se indican las librerías más conocidas para tratar/generar información relativa al formato JSON en los diferentes lenguajes de programación.
Librería jackson-databind¶
Jackson Databind es una biblioteca de Java que forma parte del proyecto Jackson, una de las bibliotecas de código abierto más populares para el procesamiento de JSON en Java. Jackson Databind proporciona funcionalidades para mapear objetos Java a JSON (serialización) y viceversa (deserialización).
Agregar librería al proyecto¶
Para utilizar la librería hay que añadirla al proyecto en intelliJ
Nos habrá agregado la librería al proyecto
Crea los POJO que correspondan al fichero json¶
Tenemos que identificar las clases Java que corresponden al json. Por ejemplo,
{
"noticias": [
{
"fecha": "2024-04-26",
"titulo": "Descubrimiento de nueva especie de planta en la selva amazónica",
"descripcion": "Investigadores han anunciado el descubrimiento de una nueva especie de planta en la selva amazónica. La planta, que ha sido bautizada como 'Amazoniaensis flore', se caracteriza por sus grandes hojas y flores de vivos colores."
},
{
"fecha": "2024-04-25",
"titulo": "Avances en la lucha contra el cambio climático",
"descripcion": "Científicos han publicado un nuevo estudio que revela avances prometedores en la lucha contra el cambio climático. Según el estudio, las medidas de reducción de emisiones implementadas en varios países están comenzando a dar resultados tangibles en la disminución de la concentración de gases de efecto invernadero en la atmósfera."
}
]
}
Tendríamos que crear la clase con la lista de noticias.
public class Noticias {
private List<Noticia> noticias;
public List<Noticia> getNoticias() { return noticias; }
public void setNoticias(List<Noticia> value) { this.noticias = value; }
@Override
public String toString() {
return "Noticias{" +
"noticias=" + noticias +
'}';
}
Importante
La clase puede tener varios constructores, pero siempre tiene que tener el constructor por defecto sin parámetros
Una clase para las Noticias
class Noticia {
private LocalDate fecha;
private String titulo;
private String descripcion;
//es obligatorio este constructor
public Noticia() {
}
public Noticia(String fecha, String titulo, String descripcion) {
setFecha(fecha);
this.titulo = titulo;
this.descripcion = descripcion;
}
public String getDescripcion() { return descripcion; }
public void setDescripcion(String value) { this.descripcion = value; }
public String getFecha() { return fecha.toString(); }
public void setFecha(LocalDate value) { this.fecha = value; }
//no existe el tipo fecha en json
public void setFecha(String value){
this.fecha=LocalDate.parse(value);
}
public String getTitulo() { return titulo; }
public void setTitulo(String value) { this.titulo = value; }
@Override
public String toString() {
return "Noticia{" +
fecha +"\n"+
titulo+"\n"+
descripcion+
"}\n";
}
}
ObjectMapper
public static void main(String[] args) {
// Lee los datos de un archivo json
try {
//Lectura del fichero
var objectMapper = new ObjectMapper();
// Convierte el json en un objeto de tipo Noticias
Noticias noticias = objectMapper.readValue(new File("noticias.json"), Noticias.class);
System.out.println(noticias);
//Escritura fichero
//añadimos una nueva noticia
noticias.getNoticias().add(new Noticia("2024-04-24","Lanzamiento exitoso de la misión espacial a Marte","La agencia espacial internacional ha anunciado el exitoso lanzamiento de una misión espacial con destino a Marte. Esta misión, denominada 'Explorador Rojo', tiene como objetivo buscar signos de vida pasada o presente en el planeta rojo y recopilar datos sobre su geología y atmósfera."));
//Para que muestre el JSON tabulado
objectMapper.configure(SerializationFeature.INDENT_OUTPUT, true);
// Convertir objeto a un string json
String jsonString = objectMapper.writeValueAsString(noticias);
System.out.println(jsonString);
//Guardar el JSON en un fichero
objectMapper.writeValue(new File("noticias2.json"), noticias);
} catch (IOException e) {
System.out.println("Error E/S: "+e.getMessage());
} catch (Exception e){
System.out.println("Error parser json: "+e.getMessage());
}
}
Plugin de IntelliJ para crear las clases desde un json¶
IntelliJ tiene varios plugin que permiten crear las clases a partir del Json. Uno de ellos es JsonToJava
Podemos añadir el plugin
Una vez añadido(tendrás que reiniciar IntelliJ), podemos crear una primera aproximación a las clases necesarias mediante
Insertamos el json de muestra y le damos nombre a la clase superior, en nuestro caso Noticias
Nos genera las clases Java necesarias para parsear en Json.
La librería Jackson, tiene muchas utilidades. Debéis consultar la documentación técnica.
Lectura de un servicio Rest¶
Con esta librería tenemos fácil leer un servicio Web y convertirlo en objetos Java. Por ejemplo, vamos a leer un servicio de ejemplo disponible en la web
Vamos a leer todos los posts disponibles y crear un ArrayList de Posts del servicio Web
https://jsonplaceholder.typicode.com/posts
Primero definimos el POJO para el Post que define la información
class Post {
private long id;
private String title;
private String body;
private long userId;
public long getid() { return id; }
public void setid(long value) { this.id = value; }
public String getTitle() { return title; }
public void setTitle(String value) { this.title = value; }
public String getBody() { return body; }
public void setBody(String value) { this.body = value; }
public long getUserId() { return userId; }
public void setUserId(long value) { this.userId = value; }
@Override
public String toString() {
return "Post{" +
"id=" + id +
", title='" + title + '\'' +
", body='" + body + '\'' +
", userId=" + userId +
"}\n";
}
}
Para solicitar al Web Service todos los Posts es necesario saber que información contiene el JSON, en nuestro caso es una lista de Posts. Creamos un objeto URL con el endpoint y le indicamos a Jackson que queremos una Lista de Posts
public static void main(String[] args) {
String url="https://jsonplaceholder.typicode.com/posts";
List<Post> posts;
try {
ObjectMapper objectMapper = new ObjectMapper();
posts = objectMapper.readValue(new URL(url), new TypeReference<List<Post>>() {});
System.out.println(posts);
} catch (IOException e) {
throw new RuntimeException(e);
}
}