La forma más rápida para analizar JSON de cadena cuando se conoce el formato

A B C :

Quiero analizar una cadena en un objeto JSON interna (o equivalente) en Java. Las bibliotecas habituales, Gsony Jackson, son demasiado lentos para mis necesidades (> 100US para cada cuerda a JSON de análisis, de acuerdo con mis puntos de referencia). Sé que hay bibliotecas ligeramente más rápido, pero mirando a los puntos de referencia en línea, las ganancias disponibles serán pequeñas (menos de un orden de magnitud de mejora).

Si sé que el formato de la JSON con antelación, ¿hay alguna manera de analizarlo mucho más rápido? Por ejemplo, sé que la cadena será un JSON del formato:

{
   "A" : 1.0 ,
   "B" : "X"
}

es decir, sé que las dos claves serán "A" y "B", y los valores será un doble y una cadena, respectivamente. Teniendo en cuenta este conocimiento avanzado del formato, es que hay una biblioteca o algún enfoque para analizar el JSON mucho más rápido de lo habitual?

Michael Ziober:

Si usted conoce a una JSONestructura de carga útil se puede utilizar Streaming APIpara leer los datos. Creé 4 métodos diferentes para leer dada JSONla carga útil:

  1. Por defecto Gson - utilización Gsonde clases.
  2. Adaptador Gson - el uso JsonReaderde la biblioteca Gson.
  3. Por defecto Jackson - el uso ObjectMapperde Jackson.
  4. Jackson en streaming API - utilización JsonParserde clases.

Para que sea comparable todos estos métodos lleve JSONcarga útil como Stringy retorno Pojoobjeto que representa Ay Bpropiedades. Siguiente gráfico representa las diferencias:introducir descripción de la imagen aquí

Como se puede notar, Jackson's Streaming APIes la manera más rápida de deserialise su JSONcarga útil de estos 4 enfoques.

Para generar gráfico anterior, a continuación se utilizaron los datos:

1113 547 540 546 544 552 547 549 547 548 Promedio 603,3
940 455 452 456 465 459 457 458 455 455 Promedio 505,2
422 266 257 262 260 267 259 262 257 259 Promedio 277,1
202 186 184 189 185 188 182 186 187 183 Promedio 187,2

el código de prueba:

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;

import java.io.IOException;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;

public class JsonApp {

    private static final String json = "{\"A\" : 1.0 ,\"B\" : \"X\"}";

    private static final int MAX = 1_000_000;

    private static List<List<Duration>> values = new ArrayList<>();

    static {
        IntStream.range(0, 4).forEach(i -> values.add(new ArrayList<>()));
    }

    public static void main(String[] args) throws Exception {
        for (int i = 0; i < 10; i++) {
            int v = 0;
            values.get(v++).add(defaultGson());
            values.get(v++).add(gsonAdapter());
            values.get(v++).add(defaultJackson());
            values.get(v).add(jacksonJsonFactory());
        }
        values.forEach(list -> {
            list.forEach(d -> System.out.print(d.toMillis() + " "));
            System.out.println(" avg " + list.stream()
                    .mapToLong(Duration::toMillis)
                    .average().getAsDouble());
        });
    }

    static Duration defaultGson() {
        Gson gson = new Gson();

        long start = System.nanoTime();
        for (int i = MAX; i > 0; i--) {
            gson.fromJson(json, Pojo.class);
        }

        return Duration.ofNanos(System.nanoTime() - start);
    }

    static Duration gsonAdapter() throws IOException {
        PojoTypeAdapter adapter = new PojoTypeAdapter();

        long start = System.nanoTime();
        for (int i = MAX; i > 0; i--) {
            adapter.fromJson(json);
        }

        return Duration.ofNanos(System.nanoTime() - start);
    }

    static Duration defaultJackson() throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);

        long start = System.nanoTime();
        for (int i = MAX; i > 0; i--) {
            mapper.readValue(json, Pojo.class);
        }

        return Duration.ofNanos(System.nanoTime() - start);
    }

    static Duration jacksonJsonFactory() throws IOException {
        JsonFactory jfactory = new JsonFactory();

        long start = System.nanoTime();
        for (int i = MAX; i > 0; i--) {
            readPartially(jfactory);
        }
        return Duration.ofNanos(System.nanoTime() - start);
    }

    static Pojo readPartially(JsonFactory jfactory) throws IOException {
        try (JsonParser parser = jfactory.createParser(json)) {

            Pojo pojo = new Pojo();

            parser.nextToken(); // skip START_OBJECT - {
            parser.nextToken(); // skip A name
            parser.nextToken();
            pojo.A = parser.getDoubleValue();
            parser.nextToken(); // skip B name
            parser.nextToken();
            pojo.B = parser.getValueAsString();

            return pojo;
        }
    }
}

class PojoTypeAdapter extends TypeAdapter<Pojo> {

    @Override
    public void write(JsonWriter out, Pojo value) {
        throw new IllegalStateException("Implement me!");
    }

    @Override
    public Pojo read(JsonReader in) throws IOException {
        if (in.peek() == com.google.gson.stream.JsonToken.NULL) {
            in.nextNull();
            return null;
        }

        Pojo pojo = new Pojo();

        in.beginObject();
        in.nextName();
        pojo.A = in.nextDouble();
        in.nextName();
        pojo.B = in.nextString();

        return pojo;
    }
}

class Pojo {

    double A;
    String B;

    @Override
    public String toString() {
        return "Pojo{" +
                "A=" + A +
                ", B='" + B + '\'' +
                '}';
    }
}

Nota: si necesita datos muy precisos tratan de crear pruebas comparativas realizadas con excelente JMH paquete.

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=313128&siteId=1
Recomendado
Clasificación