¿Cómo ignorar propiedades desconocidas al analizar JSON en Java?

Hay propiedades desconocidas al analizar JSON en Java, de las cuales el problema más común al analizar JSON en Java con la API de Jackson es que falla cuando JSON contiene propiedades desconocidas, lo que significa que la clase Java no tiene todos los campos correspondientes a todas las propiedades de JSON. Por ejemplo, si está consumiendo JSON de un servicio web REST y al día siguiente agregaron un nuevo campo en JSON, el código se romperá porque Jackson lanzará UnrecognizedPropertyException y dejará de analizar JSON. Esto es problemático y puede causar problemas en la producción si uno no está al tanto. El problema podría haberse evitado simplemente si uno estuviera familiarizado con la biblioteca de Jackson.

Métodos:

Jackson API proporciona dos formas de ignorar los campos desconocidos. Ambos enfoques se discutirán aquí y también veremos cómo usarlos y cuándo usar @JsonIgnoreProperties y cuándo ignorar campos desconocidos en JSON globalmente en el nivel de ObjectMapper. Son los siguientes:

  1. En el nivel de clase usando la anotación @JsonIgnoreProperties .
  2. En el nivel de ObjectMapper utilizando el método configure().

Método 1: usar @JsonIgnoreProperties

Si se crea una clase de modelo para representar el JSON en Java, la clase se puede anotar como @JsonIgnoreProperties(ignoreUnknown = true) para ignorar cualquier campo desconocido. Significa que si se agrega un nuevo campo más adelante en JSON que representa este modelo, Jackson no generará la excepción UnrecognizedPropertyException al analizar JSON en Java. Este enfoque no solo ignora las propiedades desconocidas para esa clase de modelo, sino que también proporciona más control.

Ejemplo:

Java

// Java Program that demonstrates the use of
// @JsonIgnoreProperties
  
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.io.Serializable;
  
/*
 * Java Program to iterate over JSONObject of json-simple
 */
@JsonIgnoreProperties(ignoreUnknown = true)
class Student implements Serializable {
    private static final long serialVersionUID
        = -740085147914603262L;
  
    private String id;
    private String name;
    private String school;
    private String section;
    private String major;
  
    // getters and setters
    public String getID() { return id; }
  
    public void setID(String id) { this.id = id; }
  
    public String getName() { return name; }
  
    public void setName(String id) { this.name = name; }
  
    public String getSchool() { return school; }
  
    public void setSchool(String id) { this.id = id; }
  
    public String getSection() { return id; }
  
    public void setSection(String id) { this.id = id; }
  
    public String getMajor() { return id; }
  
    public void setMajor(String id) { this.id = id; }
  
    @Override public String toString()
    {
  
        return "Student{"
            + "name='" + name + '\'' + ", id='" + id + '\''
            + ", school='" + school + '\'' + ", section='"
            + section + '\'' + ", major='" + major + '\''
            + '}';
    }
}
  
class StudentMain {
    public static void main(String[] args)
        throws IOException
    {
        // JSON string
        String jsonString
            = "{\"name\":\"Krish\",\"id\":\"2019071075\"\"phone\":\"111-111-1111\"}";
        System.out.println("Input json string : ");
        System.out.println(jsonString);
        System.out.println("");
        
        // convert to object;
        Student s = toStudent(jsonString);
        
        // print information
        System.out.println("Generated java class:");
        System.out.println(s);
    }
  
    private static Student toStudent(String jsonData)
        throws IOException
    {
        // create object mapper instance
        ObjectMapper om = new ObjectMapper();
        
        // convert JSON string to Java Object
        return om.readValue(jsonData, Student.class);
    }
}

Producción:

Input json string :
{"name":"Krish","phone":"111-111-1111"}

Generated java class:
Employee{name='Krish', id='2019071075', school='null', section='null', major='null'}

Salida Explicación:

El enfoque de anotar clases con @JsonIgnoreProperties permite un control más preciso sobre qué objetos deben ignorar campos desconocidos y cuáles no. Por otro lado, un desarrollador puede olvidarse de poner la anotación en una clase y entonces podría ocurrir el problema.

Método 2: Usando Jackson

Configurar ObjectMapper es otra forma de tratar con propiedades desconocidas en JSON durante el análisis para que no falle cuando encuentre una propiedad desconocida. Esto también resuelve el problema de UnrecognizedPropertyException. 

Esta configuración se habilita llamando al método configure() como se muestra a continuación: 

import com.fasterxml.jackson.databind.DeserializationFeature; 
import com.fasterxml.jackson.databind.ObjectMapper; 

ObjectMapper objectMapper = new ObjectMapper(); 
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

Nota: Esto ignorará las propiedades desconocidas para cualquier JSON que vaya a analizar. Esta opción solo debe usarse si no puede anotar una clase con la anotación @JsonIgnoreProperties.

Ejemplo:

Java

// Java Program that demonstrates the use of ObjectMapper
// Configuration
  
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import java.io.IOException;
  
/* * Java Program to iterate over JSONObject of json-simple
 */
class JacksonTest {
    // JSON string
    private static String json
        = "{\r\n"
          + "\"name\" : \"Jack Ryan\",\r\n"
          + "\"id\" : \"2019071075\",\r\n"
          + "\"school\" : St. Jude's School,\r\n"
          + "\"section\" : B\r\n"
          + "}";
    public static void main(String args[])
        throws IOException
    {
        // create object mapper instance
        ObjectMapper om = new ObjectMapper();
        // configure ignore unknown properties
        om.configure(DeserializationFeature
                         .FAIL_ON_UNKNOWN_PROPERTIES,
                     false);
        // convert JSON string to Java Object
        Student effectiveJava
            = om.readValue(json, Student.class);
        System.out.println("Input json string");
        System.out.println(json);
        System.out.println("Generated java class: ");
        System.out.println(effectiveJava);
    }
}
  
class Student {
    private String name;
    private String id;
    private String school;
  
    public Student()
    {
        // no argument constructor required by Jackson
    }
  
    public Student(String name, String id, String school)
    {
        this.name = name;
        this.id = id;
        this.school = school;
    }
    // getters and setters
    public String getID() { return id; }
  
    public void setID(String id) { this.id = id; }
  
    public String getName() { return name; }
  
    public void setName(String id) { this.name = name; }
  
    public String getSchool() { return school; }
  
    public void setSchool(String id) { this.id = id; }
  
    @Override public String toString()
    {
        return "Student{"
            + "name='" + name + '\'' + ", id='" + id + '\''
            + ", school='" + school + '\'' + '}';
    }
}

Producción :

Input json string
 {
   "name" : "Jack Ryan",
   "id" : "2019071075",
   "school" : "St. Jude's School",
   "section" : "B" 
  } 
 Generated java class:
 Student [name=Jack Ryan, id=2019071075, school=St. Jude's School]

Salida Explicación:

El enfoque de configurar el mapeador de objetos en línea con un marco de inyección de dependencia, asegurando que se use el mismo mapeador de objetos en todo el sistema, garantizará la extinción de la excepción en toda la aplicación, pero dejando a los desarrolladores con los ojos vendados en relación con la evolución que ocurrir en la API que se está consumiendo.

Sin embargo, el enfoque preferido es ignorar las propiedades desconocidas en el nivel de clase usando @JsonIgnoreProperties(ignoreUnknown = true) y solo hacer esto en el nivel de ObjectMapper si no puede anotar su clase con esta anotación, es decir, no posee la clase. También es una buena práctica anotar su clase de modelo con @JsonIgnoreProperties para evitar problemas.

Publicación traducida automáticamente

Artículo escrito por vanshitatwr620 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 *