19

当我使用 Gson 序列化包含接近零的双精度值的对象时,它使用的是科学 E 符号:

{"doublevaule":5.6E-4}

我如何告诉 Gson 生成

{"doublevaule":0.00056}

反而?我可以实现一个自定义的 JsonSerializer,但它返回一个 JsonElement。我将不得不返回一个 JsonPrimitive,其中包含一个无法控制其序列化方式的 double。

谢谢!

4

7 回答 7

13

为什么不提供一个新的序列化器Double呢?(您可能必须重写您的对象以使用Double而不是double)。

然后在序列化器中,您可以转换为 a BigDecimal,并使用比例等。

例如

    GsonBuilder gsonBuilder = new GsonBuilder();
    gsonBuilder.registerTypeAdapter(Double.class,  new JsonSerializer<Double>() {
        @Override
        public JsonElement serialize(final Double src, final Type typeOfSrc, final JsonSerializationContext context) {
            BigDecimal value = BigDecimal.valueOf(src);

            return new JsonPrimitive(value);
        }
    });

    gson = gsonBuilder.create();

以上将呈现(比方说)9.166666E-60.000009166666

于 2013-09-19T10:55:47.340 回答
4

Brian Agnew 的回答稍作改动:

public class DoubleJsonSerializer implements JsonSerializer<Double> {
    @Override
    public JsonElement serialize(final Double src, final Type typeOfSrc, final JsonSerializationContext context) {
        BigDecimal value = BigDecimal.valueOf(src);
        try {
            value = new BigDecimal(value.toBigIntegerExact());
        } catch (ArithmeticException e) {
            // ignore
        }

        return new JsonPrimitive(value);
    }
}
于 2015-12-28T14:36:01.947 回答
2

您可以尝试扩展JsonWriter和覆盖该方法value(double)

它似乎不是为了像这样修改而构建的(您几乎需要复制现有代码),但应该可以让它工作。

不幸的是,我认为没有其他理由影响输出格式。

于 2012-06-20T12:21:11.500 回答
2

GSON 内部使用 Number#toString,所以我们只需要创建一个 Number 的新实例:

.registerTypeAdapter(Double.class, new JsonSerializer<Double>() {
    @Override
    public JsonElement serialize(final Double src, final Type typeOfSrc, final JsonSerializationContext context) {

        Number n = new Number() {

            @Override
            public long longValue() {
                return 0;
            }

            @Override
            public int intValue() {
                return 0;
            }

            @Override
            public float floatValue() {
                return 0;
            }

            @Override
            public double doubleValue() {
                return 0;
            }

            @Override
            public String toString() {
                return new BigDecimal(src).toPlainString();
            }

        };

        return new JsonPrimitive(n);
    }
})
于 2014-04-17T15:11:53.350 回答
2

Double

GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Double.class,  new JsonSerializer<Double>() {
    @Override
    public JsonElement serialize(Double originalValue, Type typeOf, JsonSerializationContext context) {
        BigDecimal bigValue = BigDecimal.valueOf(originalValue);

        return new JsonPrimitive(bigValue.toPlainString());
    }
});

之前:{“金额”:1.0E9}

之后:{“金额”:“1000000000”}

不完全完美,因为它是 JSON 中的字符串。

于 2014-04-08T19:53:00.273 回答
2

使用 Kotlin:

    val gsonBuilder = GsonBuilder()
    gsonBuilder.registerTypeAdapter(object: TypeToken<Double>() {}.type, object : JsonSerializer<Double> {
        override fun serialize(src: Double, typeOfSrc: Type, context: JsonSerializationContext): JsonElement {
            val value = BigDecimal.valueOf(src)
            return JsonPrimitive(value)
        }
    })

    val gson = gsonBuilder.create()
于 2019-07-29T13:00:29.113 回答
0

出于某种原因,我无法按照许多人的建议使用 BigDecimal 的解决方案。所以我不得不这样写:

.registerTypeAdapter(object : TypeToken<Double>() {}.type, object : JsonSerializer<Double> {
    override fun serialize(src: Double, typeOfSrc: Type, context: JsonSerializationContext): JsonElement =
        JsonPrimitive(src.toBigDecimal().toPlainString().toBigDecimal())
})
于 2020-12-23T12:47:39.837 回答