What's going wrong?
Nothing wrong because of the limitations Gson has by design: Object
and JsonElement
type adapter hierarchies cannot be overridden.
Here is the test covering all four object/number hierarchy and value/JSON tree pairs:
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));
}
}
In short JsonElement
s are considered already-serialized, so what you're looking for is hidden in testNumberObject
: define Number
as a superclass (or Float
/Double
to be most precise), and serialize an object containing fields, not JsonElement
. If you must use JsonElement
, then put a "good-formattible" value right into the Num
property (BigDecimal
should work just fine).
Update 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));
}