@@ -12,7 +12,10 @@ import io.airbyte.cdk.load.data.AirbyteType
12
12
import io.airbyte.cdk.load.data.AirbyteValue
13
13
import io.airbyte.cdk.load.data.AirbyteValueDeepCoercingMapper
14
14
import io.airbyte.cdk.load.data.EnrichedAirbyteValue
15
+ import io.airbyte.cdk.load.data.FieldCategory
15
16
import io.airbyte.cdk.load.data.IntegerValue
17
+ import io.airbyte.cdk.load.data.NullValue
18
+ import io.airbyte.cdk.load.data.ObjectType
16
19
import io.airbyte.cdk.load.data.StringValue
17
20
import io.airbyte.cdk.load.data.TimestampWithTimezoneValue
18
21
import io.airbyte.cdk.load.data.json.toAirbyteValue
@@ -34,6 +37,7 @@ import io.micronaut.context.annotation.Value
34
37
import jakarta.inject.Singleton
35
38
import java.math.BigInteger
36
39
import java.time.OffsetDateTime
40
+ import java.util.*
37
41
38
42
/* *
39
43
* Internal representation of destination messages. These are intended to be specialized for
@@ -145,7 +149,7 @@ data class DestinationRecord(
145
149
)
146
150
}
147
151
fun asDestinationRecordRaw (): DestinationRecordRaw {
148
- return DestinationRecordRaw (stream, message, serialized)
152
+ return DestinationRecordRaw (stream, message, serialized, schema )
149
153
}
150
154
}
151
155
@@ -180,7 +184,8 @@ data class EnrichedDestinationRecordAirbyteValue(
180
184
data class DestinationRecordRaw (
181
185
val stream : DestinationStream .Descriptor ,
182
186
private val rawData : AirbyteMessage ,
183
- private val serialized : String
187
+ private val serialized : String ,
188
+ private val schema : AirbyteType
184
189
) {
185
190
fun asRawJson (): JsonNode {
186
191
return rawData.record.data
@@ -200,7 +205,62 @@ data class DestinationRecordRaw(
200
205
}
201
206
202
207
fun asEnrichedDestinationRecordAirbyteValue (): EnrichedDestinationRecordAirbyteValue {
203
- TODO ()
208
+ val rawJson = asRawJson()
209
+
210
+ // Get the set of field names defined in the schema
211
+ val schemaFields =
212
+ when (schema) {
213
+ is ObjectType -> schema.properties.keys
214
+ else -> emptySet()
215
+ }
216
+
217
+ val declaredFields = mutableMapOf<String , EnrichedAirbyteValue >()
218
+ val airbyteMetaFields = mutableMapOf<String , EnrichedAirbyteValue >()
219
+ val undeclaredFields = mutableMapOf<String , JsonNode >()
220
+
221
+ // Process fields from the raw JSON
222
+ rawJson.fields().forEach { (fieldName, fieldValue) ->
223
+ when {
224
+ schemaFields.contains(fieldName) -> {
225
+ // Declared field (exists in schema)
226
+ val fieldType =
227
+ (schema as ObjectType ).properties[fieldName]?.type
228
+ ? : throw IllegalStateException (
229
+ " Field '$fieldName ' exists in schema keys but not in properties"
230
+ )
231
+
232
+ val airbyteValue =
233
+ if (fieldValue.isNull) NullValue else fieldValue.toAirbyteValue()
234
+ declaredFields[fieldName] =
235
+ EnrichedAirbyteValue (
236
+ value = airbyteValue,
237
+ type = fieldType,
238
+ name = fieldName,
239
+ fieldCategory = FieldCategory .CLIENT_DATA
240
+ )
241
+ }
242
+ else -> {
243
+ // Undeclared field (not in schema)
244
+ undeclaredFields[fieldName] = fieldValue
245
+ }
246
+ }
247
+ }
248
+
249
+ return EnrichedDestinationRecordAirbyteValue (
250
+ stream = stream,
251
+ declaredFields = declaredFields,
252
+ airbyteMetaFields = airbyteMetaFields,
253
+ undeclaredFields = undeclaredFields,
254
+ emittedAtMs = rawData.record.emittedAt,
255
+ meta =
256
+ Meta (
257
+ rawData.record.meta?.changes?.map {
258
+ Meta .Change (it.field, it.change, it.reason)
259
+ }
260
+ ? : emptyList()
261
+ ),
262
+ serializedSizeBytes = serialized.length.toLong()
263
+ )
204
264
}
205
265
}
206
266
0 commit comments