2

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?

Luke
  • 22,826
  • 31
  • 110
  • 193
Yan Zhang
  • 21
  • 1
  • 4
  • Map refers to Map. AttributeValue is com.amazonaws.services.dynamodbv2.model.AttributeValue; – Yan Zhang Mar 08 '18 at 00:48
  • Aside: if you can export in Ion format, the parsing can be easier - [example](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DataExport.Output.html) – Ruben Bartelink Jul 13 '22 at 20:47

2 Answers2

2

please use this function AWS.DynamoDB.Converter.unmarshall

Related docs: unmarshall-property

Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
Andrei
  • 279
  • 2
  • 6
0

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.

Alex
  • 27
  • 1
  • 3