Как выполнить пользовательскую сериализацию в Gson с помощью JsonElement? - PullRequest
0 голосов
/ 02 марта 2019

Я использую gson как для сериализации и десериализации java-объектов, так и для его встроенного JsonElement.Если я сериализую java-объект, то я могу зарегистрировать адаптер типа, и он будет вызываться и позволит мне обеспечить пользовательскую сериализацию.

Но когда у меня есть JsonElement, я не могу его получитькогда-либо узнавать тип, который я хочу адаптировать.Скажем, у меня есть это:

JsonArray arr = new JsonArray();
arr.add(Math.PI);
arr.add(Math.E);
System.out.println(arr.toString());

Это распечатает:

[3.141592653589793,2.718281828459045]

Но как мне ограничить это, скажем, тремя дробными цифрами?Я надеялся, что смогу добавить адаптер типа, но я ничего не могу зарегистрировать, т. Е. Методы адаптера никогда не вызываются.Я должен зарегистрировать Double, Number, JsonPrimitive или что-то еще в этом случае?Я попробовал их все, и ничего не работает.

И даже если это сработало, я думаю, что лучшее, что я мог бы сделать, - это какое-то математическое округление, потому что, если я попытался «адаптировать» число, используя, скажем, String.format() тогда результатом будет строка, а не число, и я хочу, чтобы вывод json оставался числом.

Или, может быть, я что-то упустил полностью?Вот один пример того, что я пробовал:

Gson gson = (new GsonBuilder()).registerTypeAdapter(
    JsonPrimitive.class,
    new TypeAdapter<JsonPrimitive>() {
        @Override
        public JsonPrimitive read(JsonReader reader) throws IOException {
            // never using deserialization, don't expect this to print
            System.out.println("read adapter");
            return null;
        }

        @Override
        public void write(JsonWriter writer, JsonPrimitive primitive) throws IOException {
            // this never gets called; output same as above
            System.out.println("write adapter");
            writer.nullValue();
        }
    }
).create();
System.out.println(gson.toJson(arr));

1 Ответ

0 голосов
/ 02 марта 2019

Мы не можем изменить внутренние адаптеры для классов Json*, поскольку Gson использует предопределенные com.google.gson.internal.bind.TypeAdapters.JSON_ELEMENT .Но, к счастью, мы можем предоставить нашу JsonWriter реализацию.Переопределите методы, которые вам нужны, и предоставьте свою реализацию процессу сериализации.Для округления двойных чисел используйте, например, BigDecimal.Пример пользовательской реализации:

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.stream.JsonWriter;

import java.io.IOException;
import java.io.StringWriter;
import java.math.BigDecimal;

public class GsonApp {

    public static void main(String[] args) {
        Gson gson = new GsonBuilder().create();
        JsonArray array = new JsonArray();
        array.add(Math.PI);
        array.add(Math.E);

        StringWriter stringWriter = new StringWriter();
        JsonWriter jsonWriter = new JsonWriter(stringWriter) {
            @Override
            public JsonWriter value(Number value) throws IOException {
                BigDecimal bigDecimal = BigDecimal.valueOf(value.doubleValue());
                BigDecimal result = bigDecimal.setScale(3, BigDecimal.ROUND_UP);

                return super.value(result.doubleValue());
            }
        };
        jsonWriter.setIndent("  ");

        gson.toJson(array, jsonWriter);
        System.out.println(stringWriter.toString());
    }
}

Над кодом напечатаны:

[
  3.142,
  2.719
]

См. Также:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...