当我使用 Gson 序列化包含接近零的双精度值的对象时,它使用的是科学 E 符号:
{"doublevaule":5.6E-4}
我如何告诉 Gson 生成
{"doublevaule":0.00056}
反而?我可以实现一个自定义的 JsonSerializer,但它返回一个 JsonElement。我将不得不返回一个 JsonPrimitive,其中包含一个无法控制其序列化方式的 double。
谢谢!
为什么不提供一个新的序列化器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-6
为0.000009166666
对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);
}
}
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);
}
})
为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 中的字符串。
使用 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()
出于某种原因,我无法按照许多人的建议使用 BigDecimal 的解决方案。所以我不得不这样写:
.registerTypeAdapter(object : TypeToken<Double>() {}.type, object : JsonSerializer<Double> {
override fun serialize(src: Double, typeOfSrc: Type, context: JsonSerializationContext): JsonElement =
JsonPrimitive(src.toBigDecimal().toPlainString().toBigDecimal())
})