0
votes

I have a file containing data exported from DynamoDB, it has DynamoDB's "special JSON" format:

{"key1": {"m":{"key2":{"s":"val2"},"key3":{"s":"val3"}}}}

I need to parse this file and convert the data to DynamoDB item (com.amazonaws.services.dynamodbv2.document.Item) or normal JSON (I know how to convert normal JSON to Item)

I found there are ways to convert Map to Item like the following posts: 1. Converting DynamoDB JSON to Standard JSON with Java 2. How to get the pure Json string from DynamoDB stream new image?

To use the solutions mentioned in these posts, I need to write code to convert the special JSON to Map.

Is there a native way to convert DynamoDB "special JSON" text to normal JSON or directly to DynamoDB item?

2
Map refers to Map<String, AttributeValue>. AttributeValue is com.amazonaws.services.dynamodbv2.model.AttributeValue;Yan Zhang

2 Answers

1
votes

please use this function AWS.DynamoDB.Converter.unmarshall

Related docs: unmarshall-property

0
votes

I didn't find any either so I wrote some kotlin code to do it

// convert dynamodb json map to normal json map
@Suppress("unchecked_cast")
internal fun Map<String, Any>.toSimpleMapValue(): Map<String, Any> {
    return this.mapValues { (_, v) ->
        (v as Map<String, Any>).toSimpleValue()
    }
}

@Suppress("unchecked_cast", "implicit_cast_to_any")
private fun Map<String, Any>.toSimpleValue() : Any {
    require(this.size == 1)

    val list = this.map { (k, v) ->
         when (k) {
            "BOOL" -> when (v) {
                0 -> false
                1 -> true
                else -> throw IllegalArgumentException("Unknown value $v for boolean")
            }
            "S" -> v as String
            "N" -> BigDecimal(v as String)
            "B" -> copyAllBytesFrom(v as ByteBuffer)
            "SS" -> LinkedHashSet(v as List<String>)
            "NS" -> LinkedHashSet((v as List<String>).map { BigDecimal(it) })
            "BS" -> LinkedHashSet((v as List<ByteBuffer>).map { copyAllBytesFrom(it) })
            "L" -> ArrayList((v as List<Any>).map { (it as Map<String, Any>).toSimpleValue() })
            "M" -> (v as Map<String, Any>).toSimpleMapValue()

            else -> throw IllegalArgumentException("Invalid key $k")
        }
    }

    return list[0]
}

Above should do the same ting as AWS.DynamoDB.Converter.unmarshall in Javascript SDK.

Then use Item.fromMap(newImage.toSimpleMapValue()) to convert the DynamoDB Map/Json to Item.

I didn't test all the cases, especially not sure binary type.