Repository navigation
Conversation
…d is not a string Deserializing JSON whose type field is null or a nested object/array leaked a bare UnsupportedOperationException out of JsonElement.getAsString(), bypassing the JsonParseException contract the adapter already uses for a missing type field. Reject non-primitive label values with a JsonParseException instead, and cover both read paths (maintainType on and off) with tests. Signed-off-by: NUAAwqy <146524024+NUAAwqy@users.noreply.github.com>
| + " because it does not define a field named " | ||
| + typeFieldName); | ||
| } | ||
| if (!labelJsonElement.isJsonPrimitive()) { |
There was a problem hiding this comment.
Just as side note: JsonArray also supports getAsString, but only if the array contains a single element.
Not sure if it is worth to keep supporting that. It seems rather unlikely to me that users rely on this (?).
There was a problem hiding this comment.
Good point — thanks for the side note. The current change keeps the existing behavior for single-element JsonArray inputs untouched (the value still goes through nextElement.getAsString()), so this PR does not regress it. Tightening to isJsonPrimitive() would be a separate behavioral change, so I would prefer to keep this PR scoped to the null / wrong-type case unless you feel otherwise.
There was a problem hiding this comment.
The current change keeps the existing behavior for single-element
JsonArrayinputs untouched (the value still goes throughnextElement.getAsString()), so this PR does not regress it.
Are you sure? The isJsonPrimitive() check you added comes before the getAsString() call. So I think it would reject for example {"type": ["CreditCard"], ...}.
Or maybe there was a misunderstanding; I am talking about labelJsonElement being a JSON array with a single element.
Tightening to
isJsonPrimitive()would be a separate behavioral change
But isn't that exactly what your PR already does? Adding a isJsonPrimitive() check?
I am not saying that this is necessarily problematic, as mentioned in my original comment. It seems unlikely that users rely on the previous JsonArray handling.
There was a problem hiding this comment.
You are right, and thanks for pushing back — I had misread the order of the checks. The isJsonPrimitive() guard runs before getAsString(), so a single-element array label such as {"type": ["CreditCard"]} is now rejected, whereas previously it went through JsonArray.getAsString() and deserialized fine. That is a real behavior change, not a no-op.
Given your note that relying on this lenient path seems unlikely, I kept the strict behavior and pinned it with a regression test (testDeserializeSingleElementArrayAsTypeField) so the decision is explicit. If you would rather preserve the old lenient single-element-array path, I'm happy to special-case it instead.
Document that the isJsonPrimitive() check rejects a single-element JsonArray type label (previously accepted through JsonArray.getAsString()).
cf84e2f to
3ad3278
Compare
Problem
RuntimeTypeAdapterFactory's read path callslabelJsonElement.getAsString()without checking the element's shape. When the JSON's type field isnullor a nested object/array,JsonElement.getAsString()throws a bareUnsupportedOperationException("JsonNull" / "JsonObject"), which escapes theJsonParseExceptioncontract the adapter already uses for a missing type field (and whichGson.fromJsondoes not wrap).Repro:
Fix
Reject non-primitive label values with a
JsonParseExceptionbefore callinggetAsString(), mirroring the existing missing-field error. Only the exception type and message change for these inputs; primitive labels (strings, and numbers/booleans via their existinggetAsString()behavior) are untouched, so no previously working input changes result. Both read paths are covered (maintainTypeon and off).Tests
Added
testDeserializeNullTypeField,testDeserializeNullTypeFieldWithMaintainTypeandtestDeserializeObjectAsTypeFieldtoRuntimeTypeAdapterFactoryTest.Before the fix (RED),
mvn -pl extras test -Dtest=RuntimeTypeAdapterFactoryTest:After the fix (GREEN), same command:
Full extras module suite (
mvn -pl extras test, JDK 17):AI assistance used for discovery; changes were verified by running the test suite locally.