🌳

DynamoDB のデータ形式からJSON形式への変換

2022/09/23に公開1

DynamoDB のデータ形式からJSON形式への変換

DynamoDBからとってきたデータが,予測していたデータ形式と異なり扱いづらいのでシンプルなJSON形式に整形し直すことができるdynamodb-data-marshallerというライブラリを使用したときに引っかかったので記録する.

https://www.npmjs.com/package/@aws/dynamodb-data-marshaller

DynamoDBからデータとフェッチしてきたときに期待されるデータ形式は以下のようになっていてほしい

{
        id: '123-ss',
        name: 'shima',
        filepass: 'Sample/sample2.mp3',
        memo: 'memomemo'
}

しかしDynamoDBのデータ形式がどのようになっているかというと

{
        id: { S: '123-ss' },
        name: { S: 'shima' },
        filepass: { S: 'Sample/sample2.mp3' },
        memo: { S: 'memomemo' }
}

このようにネストされたデータ形式になっている.これによってとても扱いにくくなる.

これをmarchellerを使用することで上のデータ形式にリバースすることができる.

扱い方は簡単で

import { marshallItem, unmarshallItem } from '@aws/dynamodb-data-marshaller';
import { UserDataSchema } from '../Schema/User'

const params = {
            Statement: 'SELECT * FROM ' + 'Sound' + ' where id=?',
            Parameters: [{ S: id }],
        };
const res = await this.client.send(new ExecuteStatementCommand(params));
if (res.Items?.length != 1) {
	throw new Error('取得できませんでした');
}

unmarshallItem(UserDataSchema, res.Items[0]);
export const UserDataSchema = {
    id: { type: 'String' },
    name: { type: 'String' },
    filepass: { type: 'String' },
    memo: { type: 'String' },
};

このようにできるはず.だったが

Type '{ type: string; }' is not assignable to type 'SchemaType'.
      Property 'members' is missing in type '{ type: string; }' but required in type 'TupleType<any[]>'

みたいなエラーが出ている.一旦ライブラリの中身を覗いてみる

export declare function unmarshallItem<T = {
    [key: string]: any;
}>(schema: Schema, input: AttributeMap, valueConstructor?: ZeroArgumentsConstructor<T>): T;

Schema というデータ形式と一致していないようだ

export interface Schema {
    [key: string]: SchemaType;
}

Schema というインターフェイスに合致させる必要があり,このSchema interface自体はkeyを持ちvalueとして,SchemaTypeというinterfaceに一致させる必要がある

このSchemaType自体は

export declare type SchemaType = AnyType | BinaryType | BooleanType | CustomType<any> | CollectionType | DateType | DocumentType<any> | HashType | ListType | MapType | NullType | NumberType | SetType | StringType | TupleType;

今回はStringTypeだけを使いたいので,

StringTypeの中を覗くと

export interface StringType extends BaseType<string>, KeyableType {
    type: 'String';
}

あれ,あってそうなのに...

よくよく自分で定義したSchemaに出ているエラーを見てみると
UserDataSchemaは

const SoundSchema: {
    id: {
        type: string;
    };
    name: {
        type: string;
    };
    filepass: {
        type: string;
	......

みたいに解釈されてしまっている.
しかしStringTypeでは'StringType'という文字列形式で解釈されるべき対処法がとりあえず直接引数に書き込むことしかできなくて悲しいがとりあえずこれでエラー自体あ解消できる

unmarshallItem(
            {
                id: { type: 'String' },
                name: { type: 'String' },
                filepass: { type: 'String' },
                memo: { type: 'String' },
                id: { type: 'String' },
            },
            res.Items[0],
        );

Discussion

cormojscormojs

const schema: { [key: string]: SchemaType } = {...} のように型注釈を付けてあげたら上手く行きました。