rustamazon-dynamodbaws-sdk-rust

AWS Rust - convert DynamoDB result JSON to (web) JSON


Currently I have a S3 static website with a javascript request that hits a Lambda which returns an Item from my dynamodb database. I think I am very close to success on this. It seems like all I need to do is convert the DynamoDB version of JSON to normal JSON such as passed over the internet.

This is some of what I have within my Rust Lambda.

use aws_config::meta::region::RegionProviderChain;
use aws_sdk_dynamodb::model::AttributeValue;
use aws_sdk_dynamodb::Client;
use lambda_runtime::{service_fn, Error as LambdaError, LambdaEvent};
use serde_json::{json, Value};
...
...
let item = client
    .get_item()
    .table_name("example_table")
    .key("example_key", AttributeValue::S(key_value.to_string()))
    .send()
    .await?;

let mapped_value = item.item().unwrap();
let json_value = json!({ "statusCode": 200, "body": format!("{:?}", mapped_value) });
Ok(json_value)

It returns a correct response, but formatted in the DynamoDB version of JSON. Here is a brief example of a piece of it.

{"items": L([M({"load": N("2"), "name": S("Superlaser"), "item_type": S("Weapon")})])}

So when my javascript on the frontend receives this response, it errors;

Error SyntaxError: Unexpected token 'N', ..."apon_lr": N("10"), ""... is not valid JSON

I have done some Googling and come across Rusoto and serde_dynamo, but I have a lot of troubles trying to mix and match these crates... and it doesn't feel right? Is there not a conversion within aws_sdk_dynamodb?

Quite similar to this StackExchange question, but for Rust rather than Node.JS or Python. Formatting DynamoDB data to normal JSON in AWS Lambda


Solution

  • What I ended up doing was using a combination of serde_dynamo::from_item and serde_json. I set up a struct..

    use serde_derive::{Deserialize, Serialize};
    use serde_dynamo::from_item;
    use serde_json::{json, Value};
    
    #[derive(Serialize, Deserialize)]
    struct S { //just for example
        txt: String,
    }
    
    let struc: S = from_item(mapped_value.clone()).expect("Should convert Item to S");
    let json_value = serde_json::to_value(struc).expect("Should serialize to JSON");
    

    The struct needs to match the structure of the object you're getting from DynamoDB. If you are returning a bunch of items there should be a corresponding serde_dynamo call.