Support byte array payloads in ProtobufMessageConverter

Prior to this commit, the `ProtobufMessageConverter` used in messaging
would try and serialize the message payload by calling "toString()" on
it in order to pass it to the Protobuf JSON encoder.
While this works for `String` payloads, this fails for `byte[]` types.

This commit ensures that such `byte[]` are first converted to `String`
instances using the given charset first.

Fixes gh-27408
This commit is contained in:
Brian Clozel 2024-06-25 21:16:50 +02:00
parent d133ab60ee
commit 6dd5c85ed0
2 changed files with 13 additions and 7 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2022 the original author or authors. * Copyright 2002-2024 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -265,7 +265,12 @@ public class ProtobufMessageConverter extends AbstractMessageConverter {
throws IOException, MessageConversionException { throws IOException, MessageConversionException {
if (contentType.isCompatibleWith(APPLICATION_JSON)) { if (contentType.isCompatibleWith(APPLICATION_JSON)) {
this.parser.merge(message.getPayload().toString(), builder); if (message.getPayload() instanceof byte[] bytes) {
this.parser.merge(new String(bytes, charset), builder);
}
else {
this.parser.merge(message.getPayload().toString(), builder);
}
} }
else { else {
throw new MessageConversionException( throw new MessageConversionException(

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2023 the original author or authors. * Copyright 2002-2024 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,6 +16,7 @@
package org.springframework.messaging.converter; package org.springframework.messaging.converter;
import java.nio.charset.StandardCharsets;
import java.util.Map; import java.util.Map;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -49,14 +50,14 @@ class ProtobufMessageConverterTests {
private Message<byte[]> messageWithoutContentType = MessageBuilder.withPayload(this.testMsg.toByteArray()).build(); private Message<byte[]> messageWithoutContentType = MessageBuilder.withPayload(this.testMsg.toByteArray()).build();
private final Message<String> messageJson = MessageBuilder.withPayload(""" private final Message<byte[]> messageJson = MessageBuilder.withPayload("""
{ {
"foo": "Foo", "foo": "Foo",
"blah": { "blah": {
"blah": 123 "blah": 123
} }
} }
""") """.getBytes(StandardCharsets.UTF_8))
.setHeader(CONTENT_TYPE, APPLICATION_JSON) .setHeader(CONTENT_TYPE, APPLICATION_JSON)
.build(); .build();
@ -113,10 +114,10 @@ class ProtobufMessageConverterTests {
Message<?> message = converter.toMessage(testMsg, new MessageHeaders(Map.of(CONTENT_TYPE, APPLICATION_JSON))); Message<?> message = converter.toMessage(testMsg, new MessageHeaders(Map.of(CONTENT_TYPE, APPLICATION_JSON)));
assertThat(message).isNotNull(); assertThat(message).isNotNull();
assertThat(message.getHeaders().get(CONTENT_TYPE)).isEqualTo(APPLICATION_JSON); assertThat(message.getHeaders().get(CONTENT_TYPE)).isEqualTo(APPLICATION_JSON);
JSONAssert.assertEquals(messageJson.getPayload(), message.getPayload().toString(), true); JSONAssert.assertEquals(new String(messageJson.getPayload()), message.getPayload().toString(), true);
//convertFrom //convertFrom
assertThat(converter.fromMessage(message, Msg.class)).isEqualTo(testMsg); assertThat(converter.fromMessage(messageJson, Msg.class)).isEqualTo(testMsg);
} }
} }