JavaRush /Blog Java /Random-ES /Mi primera experiencia con Jackson.
Иван
Nivel 23
Москва

Mi primera experiencia con Jackson.

Publicado en el grupo Random-ES
¡Hola a todos! Érase una vez, en una galaxia muy, muy lejana, se encontró un JSON muy largo... Y me dio pereza crear un POJO para él. Y me pregunté: Imagínese una situación en la que recibo una respuesta en forma de JSON con, por ejemplo, tipos de cambio. Hay muchos campos en JSON y necesito 2 de ellos. Y ahora me gustaría saber: ¿puedo crear una clase con los campos que necesito e intentar analizar este json en un objeto de clase? ¿Entenderá Jackson lo que quiero de él? Y, en consecuencia, si él entiende y puede hacerlo de esta manera, ¿cómo podrá hacerlo más correctamente y qué funcionará más rápido? Entonces, con respecto a la pregunta que tenía sobre JSON y la percepción que tiene Jackson del mismo: Jackson entenderá todo. El es inteligente. Sólo necesita un poco de ayuda con esto. Creamos un POJO, una clase Java normal, que describirá las variables que necesitamos de JSON. Diré de inmediato que para esto es muy recomendable estudiar el JSON en sí, para el cual escribimos una clase (lo más probable es que tenga clases anidadas que también deben crearse). A continuación, usando la anotación @JsonCreator sobre el constructor, mostramos que los campos de esta clase deben completarse desde JSON. En los parámetros del constructor, podemos especificar qué campos Json asignar a los campos de clase usando la anotación @JsonParam("JsonFieldName"). Si hay más campos en json de los que necesitamos (y esta era originalmente mi pregunta), debemos advertir sobre esto y explicar que no necesitamos los campos restantes. Para ello utilizamos la anotación @JsonIgnoreProperties(ignoreUnknown=true). Entonces, cuando encuentre campos desconocidos, el programa no fallará. ¡Y redoble de tambores...! Tenemos un objeto de clase con campos completos (sí, exactamente los que necesitamos) y podemos usarlo. Inicialmente, escribí mi propia clase separada con métodos estáticos que tomaban los valores que necesitaba y, si era necesario, los llevaban a una forma divina. Es una tarea ardua. Es artesanal. Estas son muletas. Aquí está la clase misma con métodos:
public class Methods {
    public static double findRes(String body, String need){
        int begin = body.indexOf(need);
        int end = body.indexOf(",", begin);
        String res = body.substring(begin, end);
        String res2 = res.substring(res.indexOf(":")+2);
        double finalRes = Double.parseDouble(res2);
        return finalRes;
    }

    public static String findUrl(String body, String need){
        int begin = body.indexOf(need) + need.length();
        int end = body.indexOf(",", begin);
        String res = body.substring(begin, end);
        String res2 = res.substring(res.indexOf(":")+1);
        return res2;
    }
}
Usar Jackson es mucho más conveniente y legible (al menos es realmente más bonito). En una conversación con nuestros hermanos mayores, lo confirmaron: es preferible utilizar bibliotecas, en nuestro caso Jackson.
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.springframework.stereotype.Component;

@Component
@JsonIgnoreProperties(ignoreUnknown = true)
public class CurrencyPojo {
    private Rates rates;

    public CurrencyPojo() {
    }

    @JsonCreator
    public CurrencyPojo(@JsonProperty("rates") Rates rates) {
        this.rates = rates;
    }

    public Rates getRates() {
        return rates;
    }

    public void setRates(Rates rates) {
        this.rates = rates;
    }

    @Override
    public String toString() {
        return "CurrencyPojo{" +
                "rates=" + rates +
                '}';
    }

    @Component
    @JsonIgnoreProperties(ignoreUnknown = true)
    public static class Rates {

        private double rub;
        private double inr;
        private double eur;

        public Rates() {
        }

        @JsonCreator
        public Rates(@JsonProperty("RUB") double rub,
                     @JsonProperty("INR") double inr,
                     @JsonProperty("EUR") double eur) {
            this.rub = rub;
            this.inr = inr;
            this.eur = eur;
        }

        public double getRub() {
            return rub;
        }

        public void setRub(double rub) {
            this.rub = rub;
        }

        public double getInr() {
            return inr;
        }

        public void setInr(double inr) {
            this.inr = inr;
        }

        public double getEur() {
            return eur;
        }

        public void setEur(double eur) {
            this.eur = eur;
        }

        @Override
        public String toString() {
            return "Rates{" +
                    "rub=" + rub +
                    ", inr=" + inr +
                    ", eur=" + eur +
                    '}';
        }
    }
}
Me gustaría llamar su atención sobre el uso de una clase anidada. Antes de esta tarea, no se me ocurría ningún uso para ellos =) Y aquí hay un ejemplo de JSON entrante: No sé cómo hacer un "spoiler", así que entrenemos nuestro dedo))
{
    "disclaimer": "Usage subject to terms: https://openexchangerates.org/terms",
    "license": "https://openexchangerates.org/license",
    "timestamp": 1638143999,
    "base": "USD",
    "rates": {
        "AED": 3.672934,
        "AFN": 95.889778,
        "ALL": 107.277494,
        "AMD": 483.27152,
        "ANG": 1.802446,
        "AOA": 585,
        "ARS": 100.99011,
        "AUD": 1.400119,
        "AWG": 1.80025,
        "AZN": 1.700805,
        "BAM": 1.734322,
        "BBD": 2,
        "BDT": 85.804468,
        "BGN": 1.727247,
        "BHD": 0.377164,
        "BIF": 1994.344572,
        "BMD": 1,
        "BND": 1.370223,
        "BOB": 6.905713,
        "BRL": 5.593606,
        "BSD": 1,
        "BTC": 0.000017488138,
        "BTN": 74.895631,
        "BWP": 11.828585,
        "BYN": 2.560653,
        "BZD": 2.015918,
        "CAD": 1.27258,
        "CDF": 2003.492833,
        "CHF": 0.92439,
        "CLF": 0.030154,
        "CLP": 831.315923,
        "CNH": 6.395085,
        "CNY": 6.393,
        "COP": 3975.845415,
        "CRC": 639.731775,
        "CUC": 1,
        "CUP": 25.75,
        "CVE": 97.95,
        "CZK": 22.7447,
        "DJF": 178.031664,
        "DKK": 6.585348,
        "DOP": 56.599119,
        "DZD": 139.135508,
        "EGP": 15.756894,
        "ERN": 15.000155,
        "ETB": 47.819833,
        "EUR": 0.885541,
        "FJD": 2.12473,
        "FKP": 0.749595,
        "GBP": 0.749595,
        "GEL": 3.095,
        "GGP": 0.749595,
        "GHS": 6.142755,
        "GIP": 0.749595,
        "GMD": 52.425,
        "GNF": 9472.013443,
        "GTQ": 7.738789,
        "GYD": 209.235741,
        "HKD": 7.7981,
        "HNL": 24.17051,
        "HRK": 6.661782,
        "HTG": 98.81349,
        "HUF": 327.09539,
        "IDR": 14379.716018,
        "ILS": 3.185445,
        "IMP": 0.749595,
        "INR": 75.050444,
        "IQD": 1458.680982,
        "IRR": 42275,
        "ISK": 130.231848,
        "JEP": 0.749595,
        "JMD": 155.740793,
        "JOD": 0.709,
        "JPY": 113.7185,
        "KES": 112.535405,
        "KGS": 84.774702,
        "KHR": 4069.37439,
        "KMF": 436.000041,
        "KPW": 900,
        "KRW": 1195.716418,
        "KWD": 0.30268,
        "KYD": 0.833396,
        "KZT": 436.292325,
        "LAK": 10839.499888,
        "LBP": 1520.868483,
        "LKR": 202.516227,
        "LRD": 142.25,
        "LSL": 16.236278,
        "LYD": 4.615464,
        "MAD": 9.244198,
        "MDL": 17.763696,
        "MGA": 3988.128848,
        "MKD": 54.637275,
        "MMK": 1790.896161,
        "MNT": 2854.559306,
        "MOP": 8.033255,
        "MRO": 356.999828,
        "MRU": 36.094075,
        "MUR": 43.067396,
        "MVR": 15.45,
        "MWK": 816.475065,
        "MXN": 21.738389,
        "MYR": 4.239,
        "MZN": 63.857001,
        "NAD": 16.26,
        "NGN": 410.875846,
        "NIO": 35.230131,
        "NOK": 9.0605,
        "NPR": 119.833306,
        "NZD": 1.465193,
        "OMR": 0.385109,
        "PAB": 1,
        "PEN": 4.033921,
        "PGK": 3.51889,
        "PHP": 50.480705,
        "PKR": 176.598456,
        "PLN": 4.168379,
        "PYG": 6826.299832,
        "QAR": 3.646364,
        "RON": 4.37388,
        "RSD": 103.877366,
        "RUB": 75.58127,
        "RWF": 1024.40338,
        "SAR": 3.7514,
        "SBD": 8.064563,
        "SCR": 14.654883,
        "SDG": 438,
        "SEK": 9.148279,
        "SGD": 1.370086,
        "SHP": 0.749595,
        "SLL": 11119.30017,
        "SOS": 580.721202,
        "SRD": 21.52,
        "SSP": 130.26,
        "STD": 21187.940504,
        "STN": 22.195,
        "SVC": 8.750748,
        "SYP": 2512.5,
        "SZL": 15.967534,
        "THB": 33.757117,
        "TJS": 11.286041,
        "TMT": 3.51,
        "TND": 2.882,
        "TOP": 2.277258,
        "TRY": 12.378954,
        "TTD": 6.78112,
        "TWD": 27.866934,
        "TZS": 2302.544214,
        "UAH": 27.094403,
        "UGX": 3563.214629,
        "USD": 1,
        "UYU": 44.148288,
        "UZS": 10783.399861,
        "VES": 4.57705,
        "VND": 22678.30849,
        "VUV": 111.998805,
        "WST": 2.563531,
        "XAF": 580.876668,
        "XAG": 0.04289544,
        "XAU": 0.00055691,
        "XCD": 2.70255,
        "XDR": 0.714635,
        "XOF": 580.876668,
        "XPD": 0.00055962,
        "XPF": 105.673123,
        "XPT": 0.00101782,
        "YER": 250.249937,
        "ZAR": 16.1344,
        "ZMW": 17.776133,
        "ZWL": 322
    }
}
Para convertir json en un objeto de clase usamos un mapeador:
ObjectMapper mapper = new ObjectMapper();
currencyPojo(un objeto нашего класса) = mapper.readValue(jsonResponse(Джсон в стринге), CurrencyPojo.class(класс, который нам нужен));
El código está funcionando, saca de este armatoste exactamente lo que necesito. Aquí está el resultado del objeto de clase después del análisis: MonedaPojo{rates=Rates{rub=73.6944, inr=75.621547, eur=0.885436}} Estoy encantado. El segundo día me doy palmadas en toda la cara y sonrío con las manos... O algo así. Los valores de las tarifas pueden variar porque El texto JSON y el objeto se imprimen desde diferentes fechas, pero en general el resultado debe ser claro. PD: Estoy escribiendo un artículo por primera vez, así que no juzgues estrictamente. Y solo soy un hacker principiante =) Amo y acepto las críticas;) PS2 Pido disculpas por las “muchas letras”, pero intenté presentar en lo que he estado trabajando durante días.
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION