|
16 | 16 |
|
17 | 17 | package dev.openfunction.invoker.runtime;
|
18 | 18 |
|
19 |
| -import com.google.gson.Gson; |
20 |
| -import com.google.gson.GsonBuilder; |
21 |
| -import com.google.gson.JsonElement; |
22 |
| -import com.google.gson.JsonObject; |
| 19 | +import com.fasterxml.jackson.core.JsonProcessingException; |
| 20 | +import com.fasterxml.jackson.databind.JsonNode; |
| 21 | +import com.fasterxml.jackson.databind.ObjectMapper; |
| 22 | +import com.fasterxml.jackson.databind.node.ObjectNode; |
23 | 23 | import io.cloudevents.CloudEvent;
|
24 | 24 | import io.cloudevents.CloudEventData;
|
| 25 | +import io.cloudevents.SpecVersion; |
25 | 26 | import io.cloudevents.core.data.BytesCloudEventData;
|
26 | 27 | import io.cloudevents.core.format.EventDeserializationException;
|
27 | 28 | import io.cloudevents.core.format.EventFormat;
|
|
32 | 33 | import org.jetbrains.annotations.NotNull;
|
33 | 34 |
|
34 | 35 | import java.net.URI;
|
35 |
| -import java.nio.charset.StandardCharsets; |
36 | 36 | import java.time.OffsetDateTime;
|
| 37 | +import java.time.format.DateTimeFormatter; |
37 | 38 | import java.util.HashMap;
|
| 39 | +import java.util.Iterator; |
38 | 40 | import java.util.Map;
|
39 | 41 | import java.util.Objects;
|
40 | 42 |
|
41 | 43 | public class JsonEventFormat implements EventFormat {
|
42 | 44 |
|
43 | 45 | public static final String CONTENT_TYPE = "application/cloudevents+json";
|
44 | 46 |
|
45 |
| - private static final Gson GSON = new GsonBuilder().serializeNulls().create(); |
| 47 | + public final static String ID = "id"; |
| 48 | + public final static String SOURCE = "source"; |
| 49 | + public final static String SPECVERSION = "specversion"; |
| 50 | + public final static String TYPE = "type"; |
| 51 | + public final static String TIME = "time"; |
| 52 | + public final static String SCHEMAURL = "schemaurl"; |
| 53 | + public final static String DATACONTENTTYPE = "datacontenttype"; |
| 54 | + public final static String DATASCHEMA = "dataschema"; |
| 55 | + public final static String SUBJECT = "subject"; |
| 56 | + public final static String DATA = "data"; |
| 57 | + public final static String EXTENSIONS = "extensions"; |
| 58 | + public final static String TRACEPARENT = "traceparent"; |
| 59 | + public final static String TRACEID = "traceid"; |
46 | 60 |
|
47 | 61 | @Override
|
48 | 62 | public byte[] serialize(@NotNull CloudEvent event) throws EventSerializationException {
|
49 |
| - JsonObject root = GSON.toJsonTree(event).getAsJsonObject(); |
| 63 | + ObjectMapper objectMapper = new ObjectMapper(); |
| 64 | + ObjectNode root = objectMapper.createObjectNode(); |
| 65 | + root.set(SPECVERSION, objectMapper.valueToTree(event.getSpecVersion().toString())); |
| 66 | + root.set(ID, objectMapper.valueToTree(event.getId())); |
| 67 | + root.set(TYPE, objectMapper.valueToTree(event.getType())); |
| 68 | + root.set(SOURCE, objectMapper.valueToTree(event.getSource())); |
| 69 | + root.set(SCHEMAURL, objectMapper.valueToTree(event.getDataSchema())); |
| 70 | + root.set(DATACONTENTTYPE, objectMapper.valueToTree(event.getDataContentType())); |
| 71 | + root.set(SUBJECT, objectMapper.valueToTree(event.getSubject())); |
| 72 | + root.set(DATASCHEMA, objectMapper.valueToTree(event.getDataSchema())); |
| 73 | + |
| 74 | + if (event.getTime() != null) { |
| 75 | + root.set(TIME, objectMapper.valueToTree(event.getTime().format(DateTimeFormatter.ISO_DATE_TIME))); |
| 76 | + } |
| 77 | + |
| 78 | + if (event.getData() != null) { |
| 79 | + root.set(DATA, objectMapper.valueToTree(new String(event.getData().toBytes()))); |
| 80 | + } |
| 81 | + |
| 82 | + ObjectNode extensions = objectMapper.createObjectNode(); |
50 | 83 | for (String key : event.getExtensionNames()) {
|
51 |
| - root.add(key, GSON.toJsonTree(event.getExtension(key))); |
| 84 | + root.set(key, objectMapper.valueToTree(event.getExtension(key))); |
| 85 | + extensions.set(key, objectMapper.valueToTree(event.getExtension(key))); |
52 | 86 | }
|
| 87 | + root.set(EXTENSIONS, extensions); |
53 | 88 |
|
54 |
| - if (root.get("traceparent") != null) { |
55 |
| - String traceparent = root.get("traceparent").getAsString(); |
| 89 | + if (root.get(TRACEPARENT) != null) { |
| 90 | + String traceparent = root.get(TRACEPARENT).asText(); |
56 | 91 | if (!Objects.equals(traceparent, "")) {
|
57 |
| - root.add("traceid", GSON.toJsonTree(traceparent)); |
| 92 | + root.set(TRACEID, objectMapper.valueToTree(traceparent)); |
58 | 93 | }
|
59 | 94 | }
|
60 | 95 |
|
61 |
| - return root.toString().getBytes(); |
| 96 | + try { |
| 97 | + return objectMapper.writeValueAsBytes(root); |
| 98 | + } catch (JsonProcessingException e) { |
| 99 | + throw new EventSerializationException(e); |
| 100 | + } |
62 | 101 | }
|
63 | 102 |
|
64 | 103 | @Override
|
65 | 104 | public CloudEvent deserialize(@NotNull byte[] bytes, @NotNull CloudEventDataMapper<? extends CloudEventData> mapper) throws EventDeserializationException {
|
66 |
| - |
67 | 105 | try {
|
68 |
| - JsonObject jsonObject = GSON.fromJson(new String(bytes, StandardCharsets.UTF_8), JsonObject.class); |
69 |
| - |
| 106 | + String specversion = null; |
70 | 107 | String id = null;
|
71 | 108 | URI source = null;
|
72 | 109 | String type = null;
|
73 | 110 | String datacontenttype = null;
|
74 | 111 | URI schemaurl = null;
|
| 112 | + URI dataschema = null; |
75 | 113 | String subject = null;
|
76 | 114 | OffsetDateTime time = null;
|
77 | 115 | BytesCloudEventData data = null;
|
78 | 116 | Map<String, Object> extensions = new HashMap<>();
|
79 |
| - for (String key : jsonObject.keySet()) { |
80 |
| - JsonElement element = jsonObject.get(key); |
81 |
| - if (element.isJsonNull()) { |
| 117 | + |
| 118 | + JsonNode root = new ObjectMapper().readTree(bytes); |
| 119 | + Iterator<String> fields = root.fieldNames(); |
| 120 | + while (fields.hasNext()) { |
| 121 | + String field = fields.next(); |
| 122 | + JsonNode node = root.get(field); |
| 123 | + if (node.isNull()) { |
82 | 124 | continue;
|
83 | 125 | }
|
84 | 126 |
|
85 |
| - switch (key) { |
86 |
| - case CloudEventV03.ID: |
87 |
| - id = element.getAsString(); |
| 127 | + switch (field) { |
| 128 | + case SPECVERSION: |
| 129 | + specversion = node.asText(); |
88 | 130 | break;
|
89 |
| - case CloudEventV03.SOURCE: |
90 |
| - source = new URI(element.getAsString()); |
| 131 | + case ID: |
| 132 | + id = node.asText(); |
91 | 133 | break;
|
92 |
| - case CloudEventV03.TYPE: |
93 |
| - type = element.getAsString(); |
| 134 | + case SOURCE: |
| 135 | + source = new URI(node.asText()); |
94 | 136 | break;
|
95 |
| - case CloudEventV03.DATACONTENTTYPE: |
96 |
| - datacontenttype = element.getAsString(); |
| 137 | + case TYPE: |
| 138 | + type = node.asText(); |
97 | 139 | break;
|
98 |
| - case CloudEventV03.SCHEMAURL: |
99 |
| - schemaurl = new URI(element.getAsString()); |
| 140 | + case DATACONTENTTYPE: |
| 141 | + datacontenttype = node.asText(); |
100 | 142 | break;
|
101 |
| - case CloudEventV1.SUBJECT: |
102 |
| - subject = element.getAsString(); |
| 143 | + case SCHEMAURL: |
| 144 | + schemaurl = new URI(node.asText()); |
103 | 145 | break;
|
104 |
| - case CloudEventV1.TIME: |
105 |
| - time = OffsetDateTime.parse(element.getAsString()); |
| 146 | + case SUBJECT: |
| 147 | + subject = node.asText(); |
106 | 148 | break;
|
107 |
| - case "data": |
108 |
| - data = BytesCloudEventData.wrap(element.getAsString().getBytes()); |
| 149 | + case TIME: |
| 150 | + time = OffsetDateTime.parse(node.asText()); |
109 | 151 | break;
|
110 |
| - case "extensions": |
111 |
| - JsonObject extensionsObject= element.getAsJsonObject(); |
112 |
| - for (String extensionKey : extensionsObject.keySet()) { |
113 |
| - extensions.put(extensionKey, extensionsObject.get(extensionKey).getAsString()); |
| 152 | + case DATASCHEMA: |
| 153 | + dataschema = new URI(node.asText()); |
| 154 | + break; |
| 155 | + case DATA: |
| 156 | + data = BytesCloudEventData.wrap(node.asText().getBytes()); |
| 157 | + break; |
| 158 | + case EXTENSIONS: |
| 159 | + Iterator<String> it = node.fieldNames(); |
| 160 | + while ( it.hasNext() ) { |
| 161 | + String name = it.next(); |
| 162 | + extensions.put(name, node.get(name)); |
114 | 163 | }
|
115 | 164 | break;
|
116 | 165 | default:
|
117 |
| - extensions.put(key, element.getAsString()); |
| 166 | + extensions.put(field, node); |
118 | 167 | break;
|
119 | 168 | }
|
120 | 169 | }
|
121 | 170 |
|
122 |
| - return new CloudEventV03(id, source, type, time, schemaurl, datacontenttype, subject, data, extensions); |
| 171 | + if (Objects.equals(specversion, SpecVersion.V1.toString())) { |
| 172 | + return new CloudEventV1(id, source, type, datacontenttype, dataschema, subject,time, data, extensions); |
| 173 | + } else { |
| 174 | + return new CloudEventV03(id, source, type, time, schemaurl, datacontenttype, subject, data, extensions); |
| 175 | + } |
123 | 176 | } catch (Exception e) {
|
124 | 177 | throw new EventDeserializationException(e);
|
125 | 178 | }
|
|
0 commit comments