Throw JsonSyntaxException instead of raw exceptions in built-in adapters - #3108
Throw JsonSyntaxException instead of raw exceptions in built-in adapters#3108yusmer96-maker wants to merge 2 commits into
Conversation
Gson.fromJson is documented to throw JsonSyntaxException for malformed input, but four groups of built-in adapters let raw NumberFormatException, IllegalArgumentException or NullPointerException escape to the caller. Callers that guard with catch (JsonParseException) do not catch these. This is the same defect class already fixed for AtomicLongArray in google#3038 and currently open for AtomicIntegerArray in google#3047 / google#3095. In each case the neighbouring target type already behaves correctly. - BitSet with a malformed number - null elements in primitive arrays (int[], double[], char[], ...) - double/float with a malformed number - null elements in collections that reject them (TreeSet, ArrayDeque, PriorityQueue, EnumSet)
There was a problem hiding this comment.
Thanks for the pull request!
Regarding the Collection#add null check, maybe something similar would be useful for the MapTypeAdapterFactory as well. Though triggering the NullPointerException there is a bit more contrived.
Consider these examples; both cause a not helpful NullPointerException:
var type = new TypeToken<TreeMap<String, Integer>>() {};
// Case 1: map in array notation
new Gson().fromJson("[[null, 1]]", type);
// Case 2: custom adapter for key type which can return null
var gson = new GsonBuilder()
.registerTypeAdapter(String.class, new TypeAdapter<String>() {
@Override
public String read(JsonReader in) throws IOException {
in.skipValue();
return null;
}
@Override
public void write(JsonWriter out, String value) throws IOException {
throw new AssertionError("not needed");
}
})
.create();
gson.fromJson("{\"arbitrary\": 1}", type);However, fixing this for MapTypeAdapterFactory might be a bit trickier because Map#containsKey or Map#put might throw the NullPointerException.
I am not a direct member of this project; feel free to consider my comments only as suggestions.
Removed comments regarding consistent handling of malformed numbers.
|
@Marcono1234 Thanks for the review. I removed both rationale comments from the
I'd lean towards leaving those. A There is also a practical reason: the null handling here only wraps On |
Purpose
Gson.fromJsonis documented as@throws JsonSyntaxException if json is not a valid representation for an object of type, but four groups of built-in adapters let a rawNumberFormatException,IllegalArgumentExceptionorNullPointerExceptionescape to the caller instead. Callers that guard withcatch (JsonParseException e)— the documented way to handle untrusted input — do not catch these.The same defect class was already fixed for
AtomicLongArrayin #3038, and #3047 / #3095 coverAtomicIntegerArray. The four groups below are different types, none of them covered by those changes.Description
["0AA"]BitSetNumberFormatExceptionint[],List<Integer>,AtomicIntegerArray[1,null]int[],double[],char[],long[],boolean[],int[][]IllegalArgumentException: nullBitSet,AtomicLongArray,List<Integer>"0AA"double,float,Double,FloatNumberFormatExceptionbyte,short,int,long,BigDecimal,BigInteger[null]TreeSet,ArrayDeque,PriorityQueue,EnumSetNullPointerExceptionArrayList,HashSetIn each case the neighbouring target type already behaves correctly, which is what makes the inconsistency visible. No public API is added or changed.
Verified on
main(2.14.1-SNAPSHOT) with JDK 21:mvn spotless:check— passes.mvn -pl gson test—Tests run: 4636, Failures: 0, Errors: 0.mvn clean verify javadoc:jarsucceeds for Gson Parent, Gson, the JPMS / GraalVM Native Image / ProGuard-R8 test modules, Gson Extras and Gson Metrics. It fails only in Gson Protobuf Support, whereprotobuf-maven-plugin:5.1.7cannot load its mojo — the same failure occurs on unmodifiedmainin my environment, so it is unrelated to this change.Checklist
null— n/a, no new public API@since $next-version$— n/aTestCase)mvn clean verify javadoc:jarpasses without errors — see the note above: it passes for every module except Gson Protobuf Support, which fails identically on unmodifiedmainhere