Introduce JsonCloudEventData (#251)
* Implemented JsonCloudEventData Signed-off-by: Francesco Guardiani <francescoguard@gmail.com> * Suggestion Signed-off-by: Francesco Guardiani <francescoguard@gmail.com>
This commit is contained in:
parent
f9e31efaa3
commit
5e747e7278
|
@ -26,6 +26,7 @@ import com.fasterxml.jackson.databind.exc.MismatchedInputException;
|
|||
import com.fasterxml.jackson.databind.node.JsonNodeType;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import io.cloudevents.CloudEvent;
|
||||
import io.cloudevents.CloudEventData;
|
||||
import io.cloudevents.SpecVersion;
|
||||
import io.cloudevents.core.builder.CloudEventBuilder;
|
||||
import io.cloudevents.core.data.BytesCloudEventData;
|
||||
|
@ -81,7 +82,7 @@ public class CloudEventDeserializer extends StdDeserializer<CloudEvent> {
|
|||
}
|
||||
}
|
||||
|
||||
byte[] data = null;
|
||||
CloudEventData data = null;
|
||||
|
||||
// Now let's handle the data
|
||||
switch (specVersion) {
|
||||
|
@ -89,16 +90,16 @@ public class CloudEventDeserializer extends StdDeserializer<CloudEvent> {
|
|||
boolean isBase64 = "base64".equals(getOptionalStringNode(this.node, this.p, "datacontentencoding"));
|
||||
if (node.has("data")) {
|
||||
if (isBase64) {
|
||||
data = node.remove("data").binaryValue();
|
||||
data = new BytesCloudEventData(node.remove("data").binaryValue());
|
||||
} else {
|
||||
if (JsonFormat.dataIsJsonContentType(contentType)) {
|
||||
// This solution is quite bad, but i see no alternatives now.
|
||||
// Hopefully in future we can improve it
|
||||
data = node.remove("data").toString().getBytes();
|
||||
data = new JsonCloudEventData(node.remove("data"));
|
||||
} else {
|
||||
JsonNode dataNode = node.remove("data");
|
||||
assertNodeType(dataNode, JsonNodeType.STRING, "data", "Because content type is not a json, only a string is accepted as data");
|
||||
data = dataNode.asText().getBytes();
|
||||
data = new BytesCloudEventData(dataNode.asText().getBytes());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -107,16 +108,16 @@ public class CloudEventDeserializer extends StdDeserializer<CloudEvent> {
|
|||
throw MismatchedInputException.from(p, CloudEvent.class, "CloudEvent cannot have both 'data' and 'data_base64' fields");
|
||||
}
|
||||
if (node.has("data_base64")) {
|
||||
data = node.remove("data_base64").binaryValue();
|
||||
data = new BytesCloudEventData(node.remove("data_base64").binaryValue());
|
||||
} else if (node.has("data")) {
|
||||
if (JsonFormat.dataIsJsonContentType(contentType)) {
|
||||
// This solution is quite bad, but i see no alternatives now.
|
||||
// Hopefully in future we can improve it
|
||||
data = node.remove("data").toString().getBytes();
|
||||
data = new JsonCloudEventData(node.remove("data"));
|
||||
} else {
|
||||
JsonNode dataNode = node.remove("data");
|
||||
assertNodeType(dataNode, JsonNodeType.STRING, "data", "Because content type is not a json, only a string is accepted as data");
|
||||
data = dataNode.asText().getBytes();
|
||||
data = new BytesCloudEventData(dataNode.asText().getBytes());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -143,7 +144,7 @@ public class CloudEventDeserializer extends StdDeserializer<CloudEvent> {
|
|||
});
|
||||
|
||||
if (data != null) {
|
||||
return visitor.end(new BytesCloudEventData(data));
|
||||
return visitor.end(data);
|
||||
}
|
||||
return visitor.end();
|
||||
} catch (IOException e) {
|
||||
|
|
|
@ -21,6 +21,7 @@ import com.fasterxml.jackson.core.JsonGenerator;
|
|||
import com.fasterxml.jackson.databind.SerializerProvider;
|
||||
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
|
||||
import io.cloudevents.CloudEvent;
|
||||
import io.cloudevents.CloudEventData;
|
||||
import io.cloudevents.core.impl.CloudEventUtils;
|
||||
import io.cloudevents.rw.CloudEventAttributesWriter;
|
||||
import io.cloudevents.rw.CloudEventExtensionsWriter;
|
||||
|
@ -113,28 +114,33 @@ public class CloudEventSerializer extends StdSerializer<CloudEvent> {
|
|||
|
||||
// Serialize data
|
||||
if (value.getData() != null) {
|
||||
byte[] data = value.getData().toBytes();
|
||||
String contentType = value.getDataContentType();
|
||||
if (shouldSerializeBase64(contentType)) {
|
||||
switch (value.getSpecVersion()) {
|
||||
case V03:
|
||||
gen.writeStringField("datacontentencoding", "base64");
|
||||
gen.writeFieldName("data");
|
||||
gen.writeBinary(data);
|
||||
break;
|
||||
case V1:
|
||||
gen.writeFieldName("data_base64");
|
||||
gen.writeBinary(data);
|
||||
break;
|
||||
}
|
||||
} else if (JsonFormat.dataIsJsonContentType(contentType)) {
|
||||
// TODO really bad b/c it allocates stuff, is there another solution out there?
|
||||
char[] dataAsString = new String(data, StandardCharsets.UTF_8).toCharArray();
|
||||
gen.writeFieldName("data");
|
||||
gen.writeRawValue(dataAsString, 0, dataAsString.length);
|
||||
CloudEventData data = value.getData();
|
||||
if (data instanceof JsonCloudEventData) {
|
||||
gen.writeObjectField("data", ((JsonCloudEventData) data).getNode());
|
||||
} else {
|
||||
gen.writeFieldName("data");
|
||||
gen.writeUTF8String(data, 0, data.length);
|
||||
byte[] dataBytes = data.toBytes();
|
||||
String contentType = value.getDataContentType();
|
||||
if (shouldSerializeBase64(contentType)) {
|
||||
switch (value.getSpecVersion()) {
|
||||
case V03:
|
||||
gen.writeStringField("datacontentencoding", "base64");
|
||||
gen.writeFieldName("data");
|
||||
gen.writeBinary(dataBytes);
|
||||
break;
|
||||
case V1:
|
||||
gen.writeFieldName("data_base64");
|
||||
gen.writeBinary(dataBytes);
|
||||
break;
|
||||
}
|
||||
} else if (JsonFormat.dataIsJsonContentType(contentType)) {
|
||||
// TODO really bad b/c it allocates stuff, is there another solution out there?
|
||||
char[] dataAsString = new String(dataBytes, StandardCharsets.UTF_8).toCharArray();
|
||||
gen.writeFieldName("data");
|
||||
gen.writeRawValue(dataAsString, 0, dataAsString.length);
|
||||
} else {
|
||||
gen.writeFieldName("data");
|
||||
gen.writeUTF8String(dataBytes, 0, dataBytes.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
gen.writeEndObject();
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
package io.cloudevents.jackson;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import io.cloudevents.CloudEventData;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* This class is a wrapper for Jackson {@link JsonNode} implementing the {@link CloudEventData}
|
||||
*/
|
||||
public class JsonCloudEventData implements CloudEventData {
|
||||
|
||||
private final JsonNode node;
|
||||
|
||||
public JsonCloudEventData(JsonNode node) {
|
||||
Objects.requireNonNull(node);
|
||||
this.node = node;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] toBytes() {
|
||||
return node.toString().getBytes();
|
||||
}
|
||||
|
||||
public JsonNode getNode() {
|
||||
return node;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
JsonCloudEventData that = (JsonCloudEventData) o;
|
||||
return Objects.equals(getNode(), that.getNode());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(getNode());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "JsonCloudEventData{" +
|
||||
"node=" + node +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -19,7 +19,10 @@ package io.cloudevents.jackson;
|
|||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
|
||||
import io.cloudevents.CloudEvent;
|
||||
import io.cloudevents.SpecVersion;
|
||||
import io.cloudevents.core.builder.CloudEventBuilder;
|
||||
import io.cloudevents.core.provider.EventFormatProvider;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
|
@ -103,7 +106,7 @@ class JsonFormatTest {
|
|||
assertThat(serialized).isNotEmpty();
|
||||
|
||||
CloudEvent output = getFormat().deserialize(serialized);
|
||||
assertThat(output).isEqualTo(input);
|
||||
assertThat(output).isEqualTo(normalizeToJsonValueIfNeeded(input));
|
||||
}
|
||||
|
||||
public static Stream<Arguments> serializeTestArgumentsDefault() {
|
||||
|
@ -151,8 +154,8 @@ class JsonFormatTest {
|
|||
public static Stream<Arguments> deserializeTestArguments() {
|
||||
return Stream.of(
|
||||
Arguments.of("v03/min.json", V03_MIN),
|
||||
Arguments.of("v03/json_data.json", V03_WITH_JSON_DATA),
|
||||
Arguments.of("v03/json_data_with_ext.json", V03_WITH_JSON_DATA_WITH_EXT),
|
||||
Arguments.of("v03/json_data.json", normalizeToJsonValueIfNeeded(V03_WITH_JSON_DATA)),
|
||||
Arguments.of("v03/json_data_with_ext.json", normalizeToJsonValueIfNeeded(V03_WITH_JSON_DATA_WITH_EXT)),
|
||||
Arguments.of("v03/base64_json_data.json", V03_WITH_JSON_DATA),
|
||||
Arguments.of("v03/base64_json_data_with_ext.json", V03_WITH_JSON_DATA_WITH_EXT),
|
||||
Arguments.of("v03/xml_data.json", V03_WITH_XML_DATA),
|
||||
|
@ -160,8 +163,8 @@ class JsonFormatTest {
|
|||
Arguments.of("v03/text_data.json", V03_WITH_TEXT_DATA),
|
||||
Arguments.of("v03/base64_text_data.json", V03_WITH_TEXT_DATA),
|
||||
Arguments.of("v1/min.json", V1_MIN),
|
||||
Arguments.of("v1/json_data.json", V1_WITH_JSON_DATA),
|
||||
Arguments.of("v1/json_data_with_ext.json", V1_WITH_JSON_DATA_WITH_EXT),
|
||||
Arguments.of("v1/json_data.json", normalizeToJsonValueIfNeeded(V1_WITH_JSON_DATA)),
|
||||
Arguments.of("v1/json_data_with_ext.json", normalizeToJsonValueIfNeeded(V1_WITH_JSON_DATA_WITH_EXT)),
|
||||
Arguments.of("v1/base64_json_data.json", V1_WITH_JSON_DATA),
|
||||
Arguments.of("v1/base64_json_data_with_ext.json", V1_WITH_JSON_DATA_WITH_EXT),
|
||||
Arguments.of("v1/xml_data.json", V1_WITH_XML_DATA),
|
||||
|
@ -185,7 +188,11 @@ class JsonFormatTest {
|
|||
);
|
||||
}
|
||||
|
||||
public static byte[] loadFile(String input) {
|
||||
private JsonFormat getFormat() {
|
||||
return (JsonFormat) EventFormatProvider.getInstance().resolveFormat(JsonFormat.CONTENT_TYPE);
|
||||
}
|
||||
|
||||
private static byte[] loadFile(String input) {
|
||||
try {
|
||||
return String.join(
|
||||
"",
|
||||
|
@ -196,8 +203,20 @@ class JsonFormatTest {
|
|||
}
|
||||
}
|
||||
|
||||
private JsonFormat getFormat() {
|
||||
return (JsonFormat) EventFormatProvider.getInstance().resolveFormat(JsonFormat.CONTENT_TYPE);
|
||||
private static CloudEvent normalizeToJsonValueIfNeeded(CloudEvent event) {
|
||||
if (event.getData() != null && JsonFormat.dataIsJsonContentType(event.getDataContentType())) {
|
||||
CloudEventBuilder builder = null;
|
||||
if (event.getSpecVersion() == SpecVersion.V1) {
|
||||
builder = CloudEventBuilder.v1(event);
|
||||
} else {
|
||||
builder = CloudEventBuilder.v03(event);
|
||||
}
|
||||
return builder
|
||||
.withData(new JsonCloudEventData(JsonNodeFactory.instance.objectNode()))
|
||||
.build();
|
||||
} else {
|
||||
return event;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue