2

I have a simple JSON and want to convert it to DynamoDB JSON. Is there any easy way to do that?

Rob Brander
  • 3,702
  • 1
  • 20
  • 33
Vikash Yadav
  • 713
  • 1
  • 9
  • 29

2 Answers2

4

If you mean JsonString to Dynamodb Map, you can use boto3. Here is the example.

import boto3
import json

json_string = '{"key1": 1, "key2": "value"}'
json_obj = json.loads(json_string)

dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('test-table')

table.put_item(Item={'pk': 'pk-value', 'map': json_obj})

If you just want to update the while Map attribute, you can use just JSON format the same as put_item.

json_string = '{"key1": 2, "key2": "value2"}'
json_obj = json.loads(json_string2)
rsp = table.update_item(
    Key={'pk': 'pk-value'},
    AttributeUpdates={'map': {'Value': json_obj2, 'Action': 'PUT'}}
)

However, If you want to update only specific nested attribute, you need to use UpdateExpression. For example, the below is code to update only key1 attribute to 'value3'.

nested_json_string = '{"nested": "key3"}'
nested_json_obj = json.loads(nested_json_string)

rsp = table.update_item(
    Key={'pk': 'pk-value'},
    UpdateExpression='SET #map.#key1 = :val3',
    ExpressionAttributeNames={'#map':  'map', '#key1': 'key1'},
    ExpressionAttributeValues={':val3': nested_json_obj}
)
SangminKim
  • 8,358
  • 14
  • 69
  • 125
  • It works on `put_item()` but in case of `update_item()` data needs to be in DynamoDB JSON format. Ex- Simple format `{"a":5}` but while update in dynamo db it should be like this - `{"a": {'N' : 5}}` – Vikash Yadav Jan 16 '20 at 18:15
  • If the `value3` is itself a JSON, then this is not working. – Vikash Yadav Jan 17 '20 at 08:29
  • @Vikash Yadav Did you even try? it works for me. I change the example with string value to jsonObj value. – SangminKim Jan 17 '20 at 09:10
  • 1
    Thanks but I came to know that there is this module in python `dynamodb_json` , that can convert json to DynamoDB json `from dynamodb_json import json_util as json dynamodb_json = json.dumps(json_)`. In above case I was directly passing the JSON string, sorry my bad. – Vikash Yadav Jan 17 '20 at 10:06
  • @SangminKim how can we achieve the same in java ? I have normal json and i want to convert it in DynamoDB JSON. On using gson, i am able to achieve it to some extent. But the datatype fields are in small letters - "s" instead of "S" as for string in dynamodb json – simran gupta Mar 17 '22 at 08:06
0

I know this is an old question, but I came across it and the accepted answer didn't help me (it seems to suggest that you can feed boto3 with plain JSON, but it didn't work for me) and the library mentioned in the comments didn't help me either.

What did work for me was using the serializer/deserializer from boto3.dynamodb.types, basically as suggested by this answer on a very similar topic.

from boto3.dynamodb.types import TypeSerializer, TypeDeserializer
import json

serializer = TypeSerializer()
deserializer = TypeDeserializer()


# for building a DynamoDB JSON from a Python object
def serialize(item):
    serialized_item = serializer.serialize(vars(item) if hasattr(item, '__dict__') else item)

    return item if 'M' not in serialized_item else serialized_item['M']


# for building a plain JSON from a DynamoDB JSON
def deserialize(dynamodb_json_string):
    return deserializer.deserialize({'M': dynamodb_json_string})


class MyItem:
    def __init__(self, some_string_value=None, some_numeric_value=None):
        self.my_key = some_string_value
        self.my_other_key = some_numeric_value

    def __str__(self):
        return json.dumps(self, default=lambda x: x.__dict__)


if __name__ == '__main__':
    my_classy_item = MyItem("my_string_value", 5)
    my_string_item = json.loads('{"my_key": "my_string_value", "my_other_key" : 5}')

    print(serialize(my_classy_item))
    print(serialize(my_string_item))
Tom
  • 92
  • 13