Разобрать только одно поле в большой строке JSON - PullRequest
0 голосов
/ 24 февраля 2019

У меня есть строка JSON следующего формата:

{

  "foo": "small_vale"  
  "baz": "large_value"
  "bar": "another_large_value"

}

Как эффективно извлечь foo, игнорируя остальные поля?По сути, я использую Gson, и я определил «худой класс» следующим образом:

MyClass {
  private String foo;
}

Если я гарантирую, что foo появится первым в строке JSON, будет ли Gson сканировать всю строкуили он достаточно умен, чтобы остановиться?

Стоит ли использовать вместо него JsonPath?

Ответы [ 2 ]

0 голосов
/ 24 февраля 2019

Чтобы ответить на этот вопрос, нам нужно посмотреть, как вы анализируете JSON.Я предполагаю, что вы используете простейшее:

Test test = gson.fromJson(new FileReader(jsonFile), Test.class);

Если это ваш случай, ответ на ваш вопрос: Gson недостаточно умен, чтобы сделать это.Если вы проверите реализацию этого метода, вы обнаружите:

public <T> T fromJson(Reader json, Class<T> classOfT) throws JsonSyntaxException, JsonIOException {
    JsonReader jsonReader = newJsonReader(json);
    Object object = fromJson(jsonReader, classOfT);
    assertFullConsumption(object, jsonReader);
    return Primitives.wrap(classOfT).cast(object);
}

Перед тем, как метод вернет значение, он проверяет, было ли использовано целое JSON, а в случае отсутствия выбрасывается JsonIOException.Gson внутренне использует TypeAdapter реализацию для данного типа.Для вашего пользовательского MyClass будет использоваться класс ReflectiveTypeAdapterFactory.Adapter, который будет использовать всю полезную нагрузку JSON.Чтобы избежать этой ситуации, вы можете написать свой собственный TypeAdapter:

class TestTypeAdapter extends TypeAdapter<Test> {

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

    @Override
    public Test read(JsonReader in) throws IOException {
        if (in.peek() == JsonToken.NULL) {
            in.nextNull();
            return null;
        }

        Test test = new Test();

        try {
            in.beginObject();
            while (in.hasNext()) {
                String name = in.nextName();
                if (name.equals("foo")) {
                    test.setFoo(in.nextString());
                    break;
                }
            }
        } catch (IllegalStateException e) {
            throw new JsonSyntaxException(e);
        }

        return test;
    }
}

Простое использование:

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonSyntaxException;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;

public class GsonApp {

    public static void main(String[] args) throws Exception {
        File jsonFile = new File("./resource/test.json").getAbsoluteFile();
        Gson gson = new GsonBuilder().create();

        Test test = gson.fromJson(new FileReader(jsonFile), Test.class);
        Test test1 = new TestTypeAdapter().fromJson(new FileReader(jsonFile));

        System.out.println(test);
        System.out.println(test1);
    }
}

class Test {

    private String foo;

    public String getFoo() {
        return foo;
    }

    public void setFoo(String foo) {
        this.foo = foo;
    }

    @Override
    public String toString() {
        return "Test{" +
                "foo='" + foo + '\'' +
                '}';
    }
}

Надпечатки кода выше:

Test{foo='small_value'}
Test{foo='small_value'}

As, выКак видите, в обоих случаях мы проанализировали small value.Вы можете проверить этот код и вычислить, насколько быстрее пользовательский TypeAdapter для вашей JSON полезной нагрузки.

Но в случае, если у вас сложная ситуация, и вам нужно проанализировать гораздо больше JSON, чтобы найти свою ценность, попробуйте использовать JSONPath решение.Вы можете начать с этого вопроса: как проанализировать огромный JSON-файл, не загружая его в память .

0 голосов
/ 24 февраля 2019

Ваш файл json недействителен.Запятые отсутствуют.Это должно выглядеть следующим образом:

{
  "foo":"small_value",
  "baz":"large_value",
  "bar":"another_large_value"
}

В этом блоге говорится, что Джексон или простой JSON - это самые быстрые способы анализа больших данных JSON.См. Главу «Результаты больших файлов» для справки.

Пример кода для Джексона: JSON Джексона - чтение ключа JSON

Показывает, как анализировать файл JSON Angполучить значение определенного элемента.

//read json file data to String
byte[] jsonData = Files.readAllBytes(Paths.get("data.json"));

//create ObjectMapper instance
ObjectMapper objectMapper = new ObjectMapper();

//read JSON like DOM Parser
JsonNode rootNode = objectMapper.readTree(jsonData);
JsonNode fooNode = rootNode.path("foo");
System.out.println("foo value = "+fooNode.asText());
...