Open NobleMathews opened 1 month ago
spring-messaging/src/main/java/org/springframework/messaging/converter/KotlinSerializationJsonMessageConverter.java:41-109 | The snippet shows the constructor of KotlinSerializationJsonMessageConverter, which needs updating to use 'ignoreUnknownKeys = true' in the Json instance to prevent exceptions from unknown JSON keys.
spring-web/src/main/java/org/springframework/http/codec/json/KotlinSerializationJsonDecoder.java:1-53 | The snippet includes the KotlinSerializationJsonDecoder class, which should be updated to catch JsonDecodingException and convert it to DecodingException, ensuring a 400 error is returned.
To address the issue of the application returning a 500 Internal Server Error when an invalid JSON body with unknown keys is sent, follow these steps:
Modify the JSON Configuration:
Update the KotlinSerializationJsonMessageConverter
to use a Json
instance configured to ignore unknown keys. This prevents exceptions from being thrown due to unexpected keys in the JSON payload.
public class KotlinSerializationJsonMessageConverter extends AbstractJsonMessageConverter {
private static final Map<Type, KSerializer<Object>> serializerCache = new ConcurrentReferenceHashMap<>();
private final Json json;
public KotlinSerializationJsonMessageConverter() {
this(Json { ignoreUnknownKeys = true });
}
public KotlinSerializationJsonMessageConverter(Json json) {
this.json = json;
}
// Existing methods...
}
Handle JSON Decoding Exceptions:
Update the KotlinSerializationJsonDecoder
to catch JsonDecodingException
and convert it to a DecodingException
. This ensures that a 400 Bad Request is returned instead of a 500 Internal Server Error.
@Override
protected Object fromJson(String payload, Type resolvedType) {
try {
return this.json.decodeFromString(serializer(resolvedType), payload);
} catch (JsonDecodingException ex) {
throw new DecodingException("JSON decoding error: " + ex.getMessage(), ex);
}
}
Implement these changes to ensure that the application handles invalid JSON inputs gracefully by returning a 400 Bad Request.
💡 To rerun Mayil, comment mayil-ai rerun
. Mayil will incorporate any new context added to the ticket. Include details in your rerun comment to guide Mayil!
Consider the following controller:
If I run
curl -X POST --location -H "Content-Type: application/json" -d '{"message2": "hello"}'
, I get a 500 instead of a 400. If I just comment out thefrom the
Body` data class, then Spring falls back to Jackson and I get a 400 instead.I did some quick debugging, and it seems that
KotlinSerializationJsonDecoder
is at fault here; if you look atorg.springframework. it is catching
com.fasterxml.jackson.core.JsonProcessingExceptionand throwing
org.springframework.core.codec.DecodingException, which is then caught by
org.springframework.web.reactive.result.method.annotation.AbstractMessageReaderArgumentResolverhashtaghandleReadErrorand converted into a
org.springframework.web.server.ServerWebInputException` which eventually results on a 400.KotlinSerializationJsonDecoder
, on the other hand, never catcheskotlinx.serialization.json.internal.JsonDecodingException
(which is thrown bydecodeFromString
) and converts it toorg.springframework.core.codec.DecodingException
, so it bubbles all the way up as a 500 error: