Измените json с помощью GSON без использования POJO

Я хочу изменить содержимое json без преобразования его в POJO. Я использую библиотеку GSON.

Ниже приведен пример использования:

String jsonString = "[{\"key1\":\"Hello\",\"key2\":\"World\"},{\"key1\":\"Nice\",\"key2\":\"Town\"}]";

JsonElement jsonElement = gson.fromJson(jsonString, JsonElement.class);     

Есть ли способ, когда я могу установить значение key1 для некоторого значения (пусть скажем, "Test" ) в каждом массиве, без преобразования вещей в POJO

Ответ 1

Здесь самое короткое, что я придумал.

JsonElement je = new Gson().fromJson(jsonString, JsonElement.class);
JsonObject jo = je.getAsJsonObject();
jo.add("key", value);

Если у вас есть JsonObject, у gson есть много методов для манипулирования им.

Ответ 2

Один из подходов состоял бы в том, чтобы просто преобразовать JSON в java.util.Map, изменить карту и перейти оттуда (что может означать сериализацию карты обратно в JSON).

Этот подход отвечает моим предпочтениям работать с правильным API для правильной работы, сводя к минимуму использование таких инструментов, как Gson, просто обрабатывать сериализацию/десериализацию (именно это я и понял). То есть, чтобы не использовать Gson API в качестве замещающей структуры данных.

Ответ 3

Вы всегда можете получить другой тип, чем JsonElement, или использовать JsonElement.getAsJsonObject для приведения объекта к объекту (если это возможно).

String jsonString = "[{\"key1\":\"Hello\",\"key2\":\"World\"}, ...]";

JsonArray jsonArray = gson.fromJson(jsonString, JsonElement.class).getAsJsonArray();
JsonObject firstObject = jsonArray.get(i).getAsJsonObject();
firstObject.addProperty("key1", "Test");

Я ошибся раньше; похоже, нет адаптера JsonArray; вам нужно будет получить JsonElement и использовать инструмент кастинга.

Ответ 4

GSON имеет два отдельных API (которые могут быть объединены): один используется для сериализации и десериализации, а другой для потоковой передачи. Если вы хотите обрабатывать потоки JSON без накладных расходов памяти или использовать динамические структуры (а не статические POJO), вы можете сделать что-то вроде:

  • создать JsonWriter (в моем примере я использую StringWriter);
  • создать JsonReader;
  • создайте цикл, который расходует события от читателя и передает их автору, возможно, внося изменения, дополнения, пропуски и т.д.

Цикл будет состоять из одного оператора switch, который должен иметь случай всех возможных событий (10 из них). Даже самый простой пример должен иметь все из них, поэтому приведенный ниже код выглядит довольно подробным. Но это очень легко расширить, и дальнейшие расширения не будут делать это намного дольше.

Пример, который добавляет "test": 1 пара для каждого объекта выглядит примерно так:

public class Whatever {

static void streamandmodify(JsonReader reader, JsonWriter writer) throws IOException {
    while (true) {
        JsonToken token = reader.peek();
        switch (token) {
        // most cases are just consume the event
        // and pass an identical one to the writer
        case BEGIN_ARRAY:
            reader.beginArray();
            writer.beginArray();
            break;
        case END_ARRAY:
            reader.endArray();
            writer.endArray();
            break;
        case BEGIN_OBJECT:
            reader.beginObject();
            writer.beginObject();

            // this is where the change happens:
            writer.name("test");
            writer.value(1);
            break;
        case END_OBJECT:
            reader.endObject();
            writer.endObject();
            break;
        case NAME:
            String name = reader.nextName();
            writer.name(name);
            break;
        case STRING:
            String s = reader.nextString();
            writer.value(s);
            break;
        case NUMBER:
            String n = reader.nextString();
            writer.value(new BigDecimal(n));
            break;
        case BOOLEAN:
            boolean b = reader.nextBoolean();
            writer.value(b);
            break;
        case NULL:
            reader.nextNull();
            writer.nullValue();
            break;
        case END_DOCUMENT:
            return;
        }
    }
}


public static void main(String[] args) throws IOException {
    // just for test:
    JsonReader jr = new JsonReader(new StringReader("{\"a\":1, \"b\":{\"c\":[1,2,3,{},{}]}}"));
    StringWriter sw = new StringWriter();
    JsonWriter jw = new JsonWriter(sw);
    streamandmodify(jr, jw);
    System.out.println(sw.getBuffer().toString());
}
}

Ответ 5

jsonString - простая, обычная строка Java; поэтому вы можете изменить его, как вам нравится, используя стандартные функции String Java и заменить подстроку key1 на Test1:

jsonString = "[{\"key1\":\"Test\",\"key2\":\"World\"},{\"key1\":\"Nice\",\"key2\":\"Town\"}]";

Конечно, String в Java неизменен, поэтому преобразование его сначала в StringBuilder, возможно, даст вам лучшую производительность в плане использования памяти.