From 79a9290781882b2d5d6e4f356a3b7a8008682e26 Mon Sep 17 00:00:00 2001 From: Isaac Aymerich Date: Mon, 5 Sep 2022 13:14:38 +0200 Subject: [PATCH] Support dynamic JSON data content type (#471) Now checks if `datacontenttype` matches the regex: `^(application|text)\/([a-zA-Z]+\+)?json$")` This regex support `application/foobar+json` or standard ``` application/json text/json ``` Signed-off-by: Isaac Aymerich Signed-off-by: alex-butcher <21243172+abutch3r@users.noreply.github.com> --- .../io/cloudevents/jackson/JsonFormat.java | 8 +++++-- .../jackson/JsonCloudEventDataTest.java | 22 +++++++++++++++---- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/formats/json-jackson/src/main/java/io/cloudevents/jackson/JsonFormat.java b/formats/json-jackson/src/main/java/io/cloudevents/jackson/JsonFormat.java index 49467980b..8454a5a22 100644 --- a/formats/json-jackson/src/main/java/io/cloudevents/jackson/JsonFormat.java +++ b/formats/json-jackson/src/main/java/io/cloudevents/jackson/JsonFormat.java @@ -29,6 +29,7 @@ import io.cloudevents.rw.CloudEventRWException; import java.io.IOException; +import java.util.regex.Pattern; /** * Implementation of {@link EventFormat} for JSON event format @@ -43,7 +44,10 @@ public final class JsonFormat implements EventFormat { * Content type associated with the JSON event format */ public static final String CONTENT_TYPE = "application/cloudevents+json"; - + /** + * JSON Data Content Type Discriminator + */ + private static final Pattern JSON_CONTENT_TYPE_PATTERN = Pattern.compile("^(application|text)\\/([a-zA-Z]+\\+)?json$"); private final ObjectMapper mapper; private final JsonFormatOptions options; @@ -214,6 +218,6 @@ public static SimpleModule getCloudEventJacksonModule(JsonFormatOptions options) static boolean dataIsJsonContentType(String contentType) { // If content type, spec states that we should assume is json - return contentType == null || contentType.startsWith("application/json") || contentType.startsWith("text/json"); + return contentType == null || JSON_CONTENT_TYPE_PATTERN.matcher(contentType).matches(); } } diff --git a/formats/json-jackson/src/test/java/io/cloudevents/jackson/JsonCloudEventDataTest.java b/formats/json-jackson/src/test/java/io/cloudevents/jackson/JsonCloudEventDataTest.java index 9a4537e12..9ae8cfc26 100644 --- a/formats/json-jackson/src/test/java/io/cloudevents/jackson/JsonCloudEventDataTest.java +++ b/formats/json-jackson/src/test/java/io/cloudevents/jackson/JsonCloudEventDataTest.java @@ -23,16 +23,21 @@ import io.cloudevents.core.mock.MyCloudEventData; import io.cloudevents.core.provider.EventFormatProvider; import io.cloudevents.core.test.Data; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.util.stream.Stream; import static org.assertj.core.api.Assertions.assertThat; public class JsonCloudEventDataTest { - @Test - public void testMapper() { + @ParameterizedTest + @MethodSource("textContentArguments") + public void testMapper(String contentType) { CloudEvent event = CloudEventBuilder.v1(Data.V1_MIN) - .withData("application/json", new JsonCloudEventData(JsonNodeFactory.instance.numberNode(10))) + .withData(contentType, new JsonCloudEventData(JsonNodeFactory.instance.numberNode(10))) .build(); byte[] serialized = EventFormatProvider.getInstance().resolveFormat(JsonFormat.CONTENT_TYPE) @@ -47,10 +52,19 @@ public void testMapper() { return new MyCloudEventData(((JsonCloudEventData) data).getNode().asInt()); }); + assertThat(deserialized.getDataContentType()) + .isEqualTo(contentType); assertThat(deserialized.getData()) .isInstanceOf(MyCloudEventData.class); assertThat(((MyCloudEventData) deserialized.getData()).getValue()) .isEqualTo(10); } + public static Stream textContentArguments() { + return Stream.of( + Arguments.of("application/json"), + Arguments.of("text/json"), + Arguments.of("application/foobar+json") + ); + } }