Выключить научную нотацию в двойной сериализации Gson
Когда я использую Gson для сериализации объекта, который содержит двойное значение, близкое к нулю, он использует научное E-нотацию:
{"doublevaule":5.6E-4}
Как сообщить Gson генерировать
{"doublevaule":0.00056}
вместо этого? Я могу реализовать пользовательский JsonSerializer, но он возвращает JsonElement. Я должен был бы вернуть JsonPrimitive, содержащий double, не имеющий контроля над тем, как это сериализуется.
Спасибо!
Ответы
Ответ 1
Почему бы не предоставить новый сериализатор для 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
Ответ 2
Небольшое изменение на Брайан Агнью ответ:
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);
}
}
Ответ 3
Вы можете попробовать JsonWriter
и переопределить метод value(double)
Кажется, он не создан так, чтобы его можно было модифицировать (вам в значительной степени нужно будет дублировать существующий код), но должно быть возможно заставить его работать.
К сожалению, я не вижу другой причины влиять на выходной формат.
Ответ 4
Внутренне 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);
}
})
Ответ 5
Создайте собственный сериализатор для 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.
Ответ 6
С 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()