This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a commit to branch camel-4.18.x
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/camel-4.18.x by this push:
     new 92f640e51cdf [backport camel-4.18.x] CAMEL-26585: camel-aws2-sns - 
serialize array attributes as valid JSON (#29180)
92f640e51cdf is described below

commit 92f640e51cdfb5e413067aadc92b7025508d8c67
Author: Guillaume Nodet <[email protected]>
AuthorDate: Wed Nov 4 20:07:52 2026 +0100

    [backport camel-4.18.x] CAMEL-26585: camel-aws2-sns - serialize array 
attributes as valid JSON (#29180)
---
 .../camel/component/aws2/sns/Sns2Producer.java     | 13 +++++-
 .../camel/component/aws2/sns/SnsProducerTest.java  | 50 ++++++++++++++++++++++
 2 files changed, 62 insertions(+), 1 deletion(-)

diff --git 
a/components/camel-aws/camel-aws2-sns/src/main/java/org/apache/camel/component/aws2/sns/Sns2Producer.java
 
b/components/camel-aws/camel-aws2-sns/src/main/java/org/apache/camel/component/aws2/sns/Sns2Producer.java
index 6bad44284148..397c1b2e6486 100644
--- 
a/components/camel-aws/camel-aws2-sns/src/main/java/org/apache/camel/component/aws2/sns/Sns2Producer.java
+++ 
b/components/camel-aws/camel-aws2-sns/src/main/java/org/apache/camel/component/aws2/sns/Sns2Producer.java
@@ -35,6 +35,7 @@ import org.apache.camel.spi.HeaderFilterStrategy;
 import org.apache.camel.support.DefaultProducer;
 import org.apache.camel.util.ObjectHelper;
 import org.apache.camel.util.URISupport;
+import org.apache.camel.util.json.Jsoner;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import software.amazon.awssdk.core.SdkBytes;
@@ -153,7 +154,7 @@ public class Sns2Producer extends DefaultProducer {
                     result.put(entry.getKey(), mav.build());
                 } else if (value instanceof List) {
                     String resultString = ((List<?>) value).stream()
-                            .map(o -> o instanceof String ? 
String.format("\"%s\"", o) : Objects.toString(o))
+                            .map(Sns2Producer::toStringArrayValue)
                             .collect(Collectors.joining(", "));
                     MessageAttributeValue.Builder mav = 
MessageAttributeValue.builder();
                     mav.dataType("String.Array");
@@ -170,6 +171,16 @@ public class Sns2Producer extends DefaultProducer {
         return result;
     }
 
+    private static String toStringArrayValue(Object value) {
+        boolean jsonPrimitive = value == null || value instanceof Boolean || 
value instanceof Number;
+        if (value instanceof Double number) {
+            jsonPrimitive = Double.isFinite(number);
+        } else if (value instanceof Float number) {
+            jsonPrimitive = Float.isFinite(number);
+        }
+        return jsonPrimitive ? Objects.toString(value) : "\"" + 
Jsoner.escape(value.toString()) + "\"";
+    }
+
     private void configureFifoAttributes(PublishRequest.Builder request, 
Exchange exchange) {
         if (getEndpoint().getConfiguration().isFifoTopic()) {
             // use strategies
diff --git 
a/components/camel-aws/camel-aws2-sns/src/test/java/org/apache/camel/component/aws2/sns/SnsProducerTest.java
 
b/components/camel-aws/camel-aws2-sns/src/test/java/org/apache/camel/component/aws2/sns/SnsProducerTest.java
index a780c490cb2d..f9154b68c223 100644
--- 
a/components/camel-aws/camel-aws2-sns/src/test/java/org/apache/camel/component/aws2/sns/SnsProducerTest.java
+++ 
b/components/camel-aws/camel-aws2-sns/src/test/java/org/apache/camel/component/aws2/sns/SnsProducerTest.java
@@ -17,10 +17,14 @@
 package org.apache.camel.component.aws2.sns;
 
 import java.util.Arrays;
+import java.util.Date;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
+import java.util.UUID;
 
 import org.apache.camel.Exchange;
+import org.apache.camel.util.json.Jsoner;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
@@ -48,6 +52,52 @@ public class SnsProducerTest {
         when(endpoint.getHeaderFilterStrategy()).thenReturn(new 
Sns2HeaderFilterStrategy());
     }
 
+    @Test
+    public void translateStringArrayEscapesJsonCharacters() throws Exception {
+        List<String> values = List.of("a\"b", "C:\\temp", "line\nbreak", 
"tab\tvalue", "\b\f\r\u0001", "caf\u00e9",
+                "application/json", "\u007f", "\u2000");
+
+        MessageAttributeValue attribute = 
producer.translateAttributes(Map.of("values", values), exchange).get("values");
+
+        assertThat(attribute.dataType(), is("String.Array"));
+        assertThat(Jsoner.deserialize(attribute.stringValue()), is(values));
+    }
+
+    @Test
+    public void translateStringArrayQuotesOtherMemberTypes() throws Exception {
+        UUID id = UUID.fromString("123e4567-e89b-12d3-a456-426614174000");
+        Date date = new Date(0);
+        List<Object> values = List.of(Membership.GOLD, 'x', id, date);
+
+        MessageAttributeValue attribute = 
producer.translateAttributes(Map.of("values", values), exchange).get("values");
+
+        assertThat(Jsoner.deserialize(attribute.stringValue()), 
is(List.of("GOLD", "x", id.toString(), date.toString())));
+    }
+
+    @Test
+    public void translateStringArrayQuotesNonFiniteNumbers() throws Exception {
+        List<Number> values = List.of(Double.NaN, Double.POSITIVE_INFINITY, 
Double.NEGATIVE_INFINITY,
+                Float.NaN, Float.POSITIVE_INFINITY, Float.NEGATIVE_INFINITY);
+
+        MessageAttributeValue attribute = 
producer.translateAttributes(Map.of("values", values), exchange).get("values");
+
+        assertThat(Jsoner.deserialize(attribute.stringValue()),
+                is(List.of("NaN", "Infinity", "-Infinity", "NaN", "Infinity", 
"-Infinity")));
+    }
+
+    @Test
+    public void translateStringArrayKeepsJsonPrimitives() {
+        List<Object> values = Arrays.asList(12, 1.5D, 2.5F, true, null);
+
+        MessageAttributeValue attribute = 
producer.translateAttributes(Map.of("values", values), exchange).get("values");
+
+        assertThat(attribute.stringValue(), is("[12, 1.5, 2.5, true, null]"));
+    }
+
+    private enum Membership {
+        GOLD
+    }
+
     @Test
     public void translateAttributes() {
         Map<String, Object> headers = new HashMap<>();

Reply via email to