在Gson双序列化中关闭科学记数法

soat7uwm  于 2022-11-06  发布在  其他
关注(0)|答案(7)|浏览(222)

当我使用Gson序列化一个包含一个接近于零的双精度值的Object时,它使用的是科学的E标记法:

{"doublevaule":5.6E-4}

我该如何让Gson

{"doublevaule":0.00056}

我可以实现一个自定义的JsonSerializer,但它返回一个JsonElement。我必须返回一个包含双精度值的JsonPrimitive,该双精度值无法控制如何序列化。
谢谢你!

yzckvree

yzckvree1#

为什么不为Double提供一个新的序列化程序呢?(您可能需要重写对象以使用Double而不是double)。
然后在串行器中,您可以将其转换为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-6渲染为0.000009166666

a14dhokn

a14dhokn2#

Brian Agnew's answer上的一个小更改:

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);
    }
}
rjee0c15

rjee0c153#

您可以尝试扩展JsonWriter并重写方法value(double)
它似乎不适合像这样修改(您几乎需要复制现有代码),但应该可以让它工作。
不幸的是,我看不出有其他原因影响输出格式。

whlutmcx

whlutmcx4#

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英寸}
之后:{“金额”:“100000000”}
因为它是JSON中的一个字符串,所以并不完美。

yhqotfr8

yhqotfr85#

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);
    }
})
i5desfxk

i5desfxk6#

与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()
bwntbbo3

bwntbbo37#

由于某种原因,我无法像很多人建议的那样,用BigDecimal来解决问题,所以我不得不这样写:

.registerTypeAdapter(object : TypeToken<Double>() {}.type, object : JsonSerializer<Double> {
    override fun serialize(src: Double, typeOfSrc: Type, context: JsonSerializationContext): JsonElement =
        JsonPrimitive(src.toBigDecimal().toPlainString().toBigDecimal())
})

相关问题