src/main/java/org/embulk/input/datastore/DatastoreInputPlugin.kt in embulk-input-datastore-0.0.3 vs src/main/java/org/embulk/input/datastore/DatastoreInputPlugin.kt in embulk-input-datastore-0.0.4

- old
+ new

@@ -59,30 +59,14 @@ datastore.run(query) .forEach { entity -> logger.debug(entity.toString()) - // TODO separate/simplify generating JSON - val pairs = entity.names.flatMap { name -> - val dsValue = entity.getValue<Value<Any>>(name) - val strVal: String? = when (dsValue.type) { - ValueType.BLOB -> (dsValue.get() as ByteArray).toString() - ValueType.BOOLEAN -> (dsValue.get() as Boolean).toString() - ValueType.DOUBLE -> (dsValue.get() as Double).toString() - ValueType.LONG -> (dsValue.get() as Long).toString() - ValueType.STRING -> "\"${dsValue.get() as String}\"" - ValueType.TIMESTAMP -> (dsValue.get() as Timestamp).toString() - else -> null // NOTE, TODO: LIST, ENTITY, ... is still unsupported - } - strVal?.let { listOf(Pair<String, String>(name, it)) } ?: listOf() - } - val json = "{" + pairs.map { pair -> - "\"${pair.first}\": ${pair.second}" - }.joinToString() + "}" + val json = entityToJsonObject(entity) + logger.debug(json) - val msgpackValue = ValueFactory.newString(json) - pageBuilder.setJson(col, msgpackValue) + pageBuilder.setJson(col, ValueFactory.newString(json)) pageBuilder.addRecord() } pageBuilder.finish() @@ -105,7 +89,64 @@ return DatastoreOptions.newBuilder() .setProjectId(task.projectId) .setCredentials(cred) .build() .service + } + + /** + * Datastore entity -> JSON String + * e.g.) '{"name": "value", ...}' + * + */ + private fun entityToJsonObject(entity: FullEntity<*>): String? { + val fields = entity.names.flatMap { name -> + val dsValue = entity.getValue<Value<Any>>(name) + val strVal = valueToField(dsValue) + strVal?.let { listOf("\"${name}\":${it}") } ?: listOf() + } + return "{" + fields.joinToString() + "}" + } + + /** + * Datastore property value list -> JSON Array + * e.g.) '[1,2,3]' + * + */ + private fun listToJsonArray(values: List<*>): String? { + // NOTE: Do unsafe cast because of type erasure... + val anyValues = values as? List<Value<Any>> + + anyValues?.let { + val fields = it.flatMap { v -> + val strVal = valueToField(v) + strVal?.let { listOf(it) } ?: listOf() + } + return "[" + fields.joinToString() + "]" + } + + return null + } + + /** + * Datastore property value -> JSON field string + * e.g.) '"name":"value"' + * + */ + private fun valueToField(dsValue: Value<Any>): String? { + return when (dsValue.type) { + ValueType.BLOB -> (dsValue.get() as ByteArray).toString() + ValueType.BOOLEAN -> (dsValue.get() as Boolean).toString() + ValueType.DOUBLE -> (dsValue.get() as Double).toString() + ValueType.ENTITY -> entityToJsonObject(dsValue.get() as FullEntity<*>) + ValueType.KEY -> (dsValue.get() as Key).toString() + ValueType.LAT_LNG -> (dsValue.get() as LatLngValue).toString() + ValueType.LIST -> listToJsonArray(dsValue.get() as List<*>) + ValueType.LONG -> (dsValue.get() as Long).toString() + ValueType.NULL -> "null" + ValueType.RAW_VALUE -> (dsValue.get() as RawValue).toString() + ValueType.STRING -> "\"${dsValue.get() as String}\"" + ValueType.TIMESTAMP -> (dsValue.get() as Timestamp).toString() + else -> null // NOTE: unexpected or unsupported type + } } }