Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Perform numeric conversion for primitive numeric type adapters #2158

Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions gson/src/main/java/com/google/gson/Gson.java
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@ private TypeAdapter<Number> doubleAdapter(boolean serializeSpecialFloatingPointV
}
double doubleValue = value.doubleValue();
checkValidFloatingPoint(doubleValue);
out.value(value);
out.value(doubleValue);
}
};
}
Expand All @@ -422,7 +422,7 @@ private TypeAdapter<Number> floatAdapter(boolean serializeSpecialFloatingPointVa
}
float floatValue = value.floatValue();
checkValidFloatingPoint(floatValue);
out.value(value);
out.value(floatValue);
Copy link
Member

@eamonnmcmanus eamonnmcmanus Oct 3, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I ran this PR against all of Google's tests, I found two failures, both linked to this line. The problem is that we've only had JsonWriter.value(float) since #2130. If people subclassed JsonWriter before then and overrode all of the value methods, they won't have overridden value(float).

Maybe that kind of subclassing is questionable, I'm not sure. It's certainly rare: we have only 5 subclasses of JsonWriter, though 3 of them do override the value methods. Still, I think it would safest to undo this change, and then probably also the change in doubleAdapter for symmetry.

Copy link
Collaborator Author

@Marcono1234 Marcono1234 Oct 3, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm ok, I think I also need to adjust then TypeAdapters.FLOAT as well because that now calls value(float) too. To keep the numeric conversion but also remain backward compatible it is now checking that the value is a Float, converting it if necessary and calls value(Number) again.

I am not changing doubleAdapter though since that is similar to the TypeAdapters changes.

}
};
}
Expand Down
36 changes: 30 additions & 6 deletions gson/src/main/java/com/google/gson/internal/bind/TypeAdapters.java
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,11 @@ public Number read(JsonReader in) throws IOException {
}
@Override
public void write(JsonWriter out, Number value) throws IOException {
out.value(value);
if (value == null) {
out.nullValue();
} else {
out.value(value.byteValue());
}
}
};

Expand Down Expand Up @@ -223,7 +227,11 @@ public Number read(JsonReader in) throws IOException {
}
@Override
public void write(JsonWriter out, Number value) throws IOException {
out.value(value);
if (value == null) {
out.nullValue();
} else {
out.value(value.shortValue());
}
}
};

Expand All @@ -245,7 +253,11 @@ public Number read(JsonReader in) throws IOException {
}
@Override
public void write(JsonWriter out, Number value) throws IOException {
out.value(value);
if (value == null) {
out.nullValue();
} else {
out.value(value.intValue());
}
}
};
public static final TypeAdapterFactory INTEGER_FACTORY
Expand Down Expand Up @@ -323,7 +335,11 @@ public Number read(JsonReader in) throws IOException {
}
@Override
public void write(JsonWriter out, Number value) throws IOException {
out.value(value);
if (value == null) {
out.nullValue();
} else {
out.value(value.longValue());
}
}
};

Expand All @@ -338,7 +354,11 @@ public Number read(JsonReader in) throws IOException {
}
@Override
public void write(JsonWriter out, Number value) throws IOException {
out.value(value);
if (value == null) {
out.nullValue();
} else {
out.value(value.floatValue());
}
}
};

Expand All @@ -353,7 +373,11 @@ public Number read(JsonReader in) throws IOException {
}
@Override
public void write(JsonWriter out, Number value) throws IOException {
out.value(value);
if (value == null) {
out.nullValue();
} else {
out.value(value.doubleValue());
}
}
};

Expand Down
60 changes: 60 additions & 0 deletions gson/src/test/java/com/google/gson/functional/PrimitiveTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ public void testPrimitiveIntegerAutoboxedDeserialization() {
public void testByteSerialization() {
assertEquals("1", gson.toJson(1, byte.class));
assertEquals("1", gson.toJson(1, Byte.class));
assertEquals(Byte.toString(Byte.MIN_VALUE), gson.toJson(Byte.MIN_VALUE, Byte.class));
assertEquals(Byte.toString(Byte.MAX_VALUE), gson.toJson(Byte.MAX_VALUE, Byte.class));
// Should perform narrowing conversion
assertEquals("-128", gson.toJson(128, Byte.class));
assertEquals("1", gson.toJson(1.5, Byte.class));
}

public void testByteDeserialization() {
Expand Down Expand Up @@ -102,6 +107,13 @@ public void testByteDeserializationLossy() {
public void testShortSerialization() {
assertEquals("1", gson.toJson(1, short.class));
assertEquals("1", gson.toJson(1, Short.class));
assertEquals(Short.toString(Short.MIN_VALUE), gson.toJson(Short.MIN_VALUE, Short.class));
assertEquals(Short.toString(Short.MAX_VALUE), gson.toJson(Short.MAX_VALUE, Short.class));
// Should perform widening conversion
assertEquals("1", gson.toJson((byte) 1, Short.class));
// Should perform narrowing conversion
assertEquals("-32768", gson.toJson(32768, Short.class));
assertEquals("1", gson.toJson(1.5, Short.class));
}

public void testShortDeserialization() {
Expand Down Expand Up @@ -137,6 +149,54 @@ public void testShortDeserializationLossy() {
}
}

public void testIntSerialization() {
assertEquals("1", gson.toJson(1, int.class));
assertEquals("1", gson.toJson(1, Integer.class));
assertEquals(Integer.toString(Integer.MIN_VALUE), gson.toJson(Integer.MIN_VALUE, Integer.class));
assertEquals(Integer.toString(Integer.MAX_VALUE), gson.toJson(Integer.MAX_VALUE, Integer.class));
// Should perform widening conversion
assertEquals("1", gson.toJson((byte) 1, Integer.class));
// Should perform narrowing conversion
assertEquals("-2147483648", gson.toJson(2147483648L, Integer.class));
assertEquals("1", gson.toJson(1.5, Integer.class));
}

public void testLongSerialization() {
assertEquals("1", gson.toJson(1L, long.class));
assertEquals("1", gson.toJson(1L, Long.class));
assertEquals(Long.toString(Long.MIN_VALUE), gson.toJson(Long.MIN_VALUE, Long.class));
assertEquals(Long.toString(Long.MAX_VALUE), gson.toJson(Long.MAX_VALUE, Long.class));
// Should perform widening conversion
assertEquals("1", gson.toJson((byte) 1, Long.class));
// Should perform narrowing conversion
assertEquals("1", gson.toJson(1.5, Long.class));
}

public void testFloatSerialization() {
assertEquals("1.5", gson.toJson(1.5f, float.class));
assertEquals("1.5", gson.toJson(1.5f, Float.class));
assertEquals(Float.toString(Float.MIN_VALUE), gson.toJson(Float.MIN_VALUE, Float.class));
assertEquals(Float.toString(Float.MAX_VALUE), gson.toJson(Float.MAX_VALUE, Float.class));
// Should perform widening conversion
assertEquals("1.0", gson.toJson((byte) 1, Float.class));
// (This widening conversion is actually lossy)
assertEquals(Float.toString(Long.MAX_VALUE - 10L), gson.toJson(Long.MAX_VALUE - 10L, Float.class));
// Should perform narrowing conversion
gson = new GsonBuilder().serializeSpecialFloatingPointValues().create();
assertEquals("Infinity", gson.toJson(Double.MAX_VALUE, Float.class));
}

public void testDoubleSerialization() {
assertEquals("1.5", gson.toJson(1.5, double.class));
assertEquals("1.5", gson.toJson(1.5, Double.class));
assertEquals(Double.toString(Double.MIN_VALUE), gson.toJson(Double.MIN_VALUE, Double.class));
assertEquals(Double.toString(Double.MAX_VALUE), gson.toJson(Double.MAX_VALUE, Double.class));
// Should perform widening conversion
assertEquals("1.0", gson.toJson((byte) 1, Double.class));
// (This widening conversion is actually lossy)
assertEquals(Double.toString(Long.MAX_VALUE - 10L), gson.toJson(Long.MAX_VALUE - 10L, Double.class));
}

public void testPrimitiveIntegerAutoboxedInASingleElementArraySerialization() {
int target[] = {-9332};
assertEquals("[-9332]", gson.toJson(target));
Expand Down