Gson无法调用自定义序列化程序

62o28rlo  于 2022-11-06  发布在  其他
关注(0)|答案(2)|浏览(227)

我一直在尝试按照here给出的建议,关闭用Json表示的数值的科学记数法。我遇到的问题是,我的自定义序列化程序从未被调用。
我尝试了不同的代码变体,最终得到的结果是:

public class TestExternaliser {
    static class SpecialSerializer implements JsonSerializer<Object> {
        @Override
        public JsonElement serialize(Object x,
                                     Type type,
                                     JsonSerializationContext jsonSerializationContext) {
            return new JsonPrimitive("xxx");
        }
    }

    public static void main(String... args) {
        JsonObject root = new JsonObject();

        root.addProperty("String", "String");
        root.addProperty("Num", Integer.valueOf(123));
        root.addProperty("Bool", Boolean.TRUE);

        Gson gson = new GsonBuilder()
                .registerTypeHierarchyAdapter(Object.class, new SpecialSerializer())
                .setPrettyPrinting()
                .create();

        System.out.println(gson.toJson(root));
    }
}

如果我正确理解了API,那么这段代码将对所有值使用自定义序列化,因此它应该为所有值生成"xxx",但我一直得到的是:

{
  "String": "String",
  "Num": 123,
  "Bool": true
}

出什么事了?

yyyllmsg

yyyllmsg1#

出什么事了?
没有什么不对的,因为Gson在设计上有局限性:不能覆盖ObjectJsonElement类型适配器层次。
下面的测试涵盖了所有四个对象/数字层次结构和值/JSON树对:

public final class LimitationsTest {

    private static final JsonSerializer<Object> defaultJsonSerializer = (src, typeOfSrc, context) -> new JsonPrimitive("xxx");

    private static final Gson objectDefaultsGson = new GsonBuilder()
            .registerTypeHierarchyAdapter(Object.class, defaultJsonSerializer)
            .create();

    private static final Gson numberDefaultsGson = new GsonBuilder()
            .registerTypeHierarchyAdapter(Number.class, defaultJsonSerializer)
            .create();

    private static final class Value {
        @SerializedName("String")
        private String string;
        @SerializedName("Num")
        private Number num;
        @SerializedName("Bool")
        private Boolean bool;
    }

    private static final Object object;
    private static final JsonElement jsonElement;

    static {
        final Value newObject = new Value();
        newObject.string = "String";
        newObject.num = 123;
        newObject.bool = Boolean.TRUE;
        object = newObject;
        final JsonObject newJsonElement = new JsonObject();
        newJsonElement.addProperty("String", "String");
        newJsonElement.addProperty("Num", 123);
        newJsonElement.addProperty("Bool", Boolean.TRUE);
        jsonElement = newJsonElement;
    }

    @Test
    public void testObjectObject() {
        Assertions.assertEquals("\"xxx\"", objectDefaultsGson.toJson(object));
    }

    @Test
    public void testObjectJsonElement() {
        Assertions.assertEquals("{\"String\":\"String\",\"Num\":123,\"Bool\":true}", objectDefaultsGson.toJson(jsonElement));
    }

    @Test
    public void testNumberObject() {
        Assertions.assertEquals("{\"String\":\"String\",\"Num\":\"xxx\",\"Bool\":true}", numberDefaultsGson.toJson(object));
    }

    @Test
    public void testNumberJsonElement() {
        Assertions.assertEquals("{\"String\":\"String\",\"Num\":123,\"Bool\":true}", numberDefaultsGson.toJson(jsonElement));
    }

}

简而言之,JsonElement被认为已经序列化了,所以您要查找的内容隐藏在testNumberObject中:将Number定义为超类(或者更准确地说是Float/Double),并序列化包含字段的对象,而不是JsonElement。如果必须使用JsonElement,则将一个“可正确格式化”的值直接放入Num属性(BigDecimal应该可以正常工作)。
更新1.

@Test
public void testNoScientificNotationForJsonElement() {
    final JsonObject newJsonElement = new JsonObject();
    newJsonElement.addProperty("a", new BigDecimal(new BigDecimal("1E+10").toPlainString()));
    newJsonElement.addProperty("b", new BigDecimal("1E+10") {
        @Override
        public String toString() {
            return toPlainString();
        }
    });
    final Gson gson = new Gson();
    Assertions.assertEquals("{\"a\":10000000000,\"b\":10000000000}", gson.toJson(newJsonElement));
}
niknxzdl

niknxzdl2#

在剧作家,微软图书馆,和rust-rcon图书馆,类似的事情发生在我身上。我离开你的链接。
发生此错误的原因是您安装了jdk 11或更高版本以及2.8.6之前的gson
https://github.com/microsoft/playwright-java/issues/245#issuecomment-775351308https://github.com/MrGraversen/rust-rcon/pull/2#event-4300625968
解决办法是去gson的最新版本,虽然这个版本是他们用的那个,我把它加到我的POM里强迫maven让剩下的依赖项都用最新的版本,试着看看告诉我!

<dependency>
   <groupId>com.google.code.gson</groupId>
   <artifactId>gson</artifactId>
   <version>2.8.6</version>
</dependency>

尝试此解决方案:D

相关问题