This library provides an marshallItem
and unmarshallItem
functions that
convert native JavaScript values to DynamoDB AttributeValues and back again,
respectively, based on a defined schema. While many JavaScript values map
cleanly to DynamoDB data types and vice versa, schemas allow you to losslessly
persist any JavaScript type, including dates, class instances, and empty
strings.
To use the data marshaller, begin by defining a schema that describes the relationship between your application's domain objects and their serialized form in a DynamoDB table:
const schema = {
foo: {type: 'Binary'},
bar: {type: 'Boolean'},
baz: {type: 'String'},
quux: {
type: 'Document',
members: {
fizz: {type: 'Set', memberType: 'String'},
buzz: {
type: 'Tuple',
members: [
{
type: 'List',
memberType: {type: 'Set', memberType: 'Number'},
},
{
type: 'Map',
memberType: {type: 'Date'},
}
]
},
},
},
};
This schema may be used to marshall JavaScript values to DynamoDB attribute values:
import {marshallItem} from '@aws/dynamodb-data-marshaller';
const marshalled = marshallItem(schema, {
foo: Uint8Array.from([0xde, 0xad, 0xbe, 0xef]),
bar: false,
baz: '',
quux: {
fizz: new Set(['a', 'b', 'c']),
buzz: [
[
new Set([1, 2, 3]),
new Set([2, 3, 4]),
new Set([3, 4, 5]),
],
new Map([
['now', new Date()],
['then', new Date(0)],
]),
]
}
});
The schema can also be used to unmarshall DynamoDB attribute values back to their original JavaScript representation:
import {unmarshallItem} from '@aws/dynamodb-data-marshaller';
const unmarshalled = unmarshallItem(schema, {
foo: {B: Uint8Array.from([0xde, 0xad, 0xbe, 0xef])},
bar: {BOOL: false},
baz: {NULL: true},
quux: {
fizz: {SS: ['a', 'b', 'c']},
buzz: {
L: [
L: [
{NS: ['1', '2', '3']},
{NS: ['2', '3', '4']},
{NS: ['3', '4', '5']},
],
M: {
now: {N: '1507189047'},
then: {N: '0'}
},
],
},
},
});
DynamoDB tables must define a hash key and may optionally define a range key. In
DynamoDB documentation, these keys are sometimes referred to as partition and
sort keys, respectively. To declare a property to be a key, add a keyType
property to its property schema (example taken from the DynamoDB developer
guide):
// Table model taken from http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GSI.html
const gameScores = {
UserId: {
type: 'String',
keyType: 'HASH'
},
GameTitle: {
type: 'String',
keyType: 'RANGE'
},
TopScore: {type: 'Number'},
TopScoreDateTime: {type: 'Date'},
Wins: {type: 'Number'},
Losses: {type: 'Number'}
};
The keyType
attribute may only be used in types that are serialized as
strings, numbers, or binary attributes. In addition to 'String'
, 'Number'
,
and 'Binary'
properties, it may be used on 'Date'
and 'Custom'
properties.
Index keys are specified using an object mapping index names to the key type as
which the value is used in a given index. To continue with the gameScores
example given above, you could add the index key declarations described in the
DynamoDB Global Secondary Index developer guide
as follows:
const gameScores = {
UserId: {
type: 'String',
keyType: 'HASH'
},
GameTitle: {
type: 'String',
keyType: 'RANGE',
indexKeyConfigurations: {
GameTitleIndex: 'HASH'
}
},
TopScore: {
type: 'Number',
indexKeyConfigurations: {
GameTitleIndex: 'RANGE'
}
},
TopScoreDateTime: {type: 'Date'},
Wins: {type: 'Number'},
Losses: {type: 'Number'}
};
Any property schema may define a defaultProvider
function to be called when a
field is undefined
in the input provided to marshallItem
. This function must
return a raw JavaScript value and should not return an already-marshalled
DynamoDB AttributeValue shape.
const uuidV4 = require('uuid/v4');
const schema = {
key: {
type: 'String',
defaultProvider: uuidV4,
keyType: 'HASH',
},
// ...
};
Will be marshalled and unmarshalled using the @aws/dynamodb-auto-marshaller
package, which detects the type of a given value at runtime.
const anyProperty = {
type: 'Any',
// optionally, you may specify configuration options for the
// @aws/dynamodb-auto-marshaller package's Marshaller class:
unwrapNumbers: false,
onInvalid: 'omit',
onEmpty: 'nullify',
};
Used for ArrayBuffer
and ArrayBufferView
objects, as well as Node.JS
buffers.
May be used as a table or index key.
const binaryProperty = {type: 'Binary'};
Used for true
/false
values.
const booleanProperty = {type: 'Boolean'};
Denotes a list of untyped items. The constituent items will be marshalled and
unmarshalled using the @aws/dynamodb-auto-marshaller
.
const collectionProperty = {
type: 'Collection',
// optionally, you may specify configuration options for the
// @aws/dynamodb-auto-marshaller package's Marshaller class:
unwrapNumbers: false,
onInvalid: 'omit',
onEmpty: 'nullify',
};
Allows the use of bespoke marshalling and unmarshalling functions. The type
definition for a 'Custom'
property must include a marshall
function that
converts the type's JavaScript representation to a DynamoDB AttributeValue and
an unmarshall
function that converts the AttributeValue back to a JavaScript
value.
May be used as a table or index key.
// This custom property handles strings
const customProperty = {
type: 'Custom',
marshall(input) {
return {S: input};
},
unmarshall(persistedValue) {
return persistedValue.S;
}
};
Used for time data. Dates will be serialized to DynamoDB as epoch timestamps for easy integration with DynamoDB's time-to-live feature. As a result, timezone information will not be persisted.
May be used as a table or index key.
const dateProperty = {type: 'Date'};
Used for object values that have their own schema and (optionally) constructor.
class MyCustomDocument {
method() {
// pass
}
get computedProperty() {
// pass
}
}
class documentSchema = {
fizz: {type: 'String'},
buzz: {type: 'Number'},
pop: {type: 'Date'}
}
const documentProperty = {
type: 'Document',
members: documentSchema,
// optionally, you may specify a constructor to use to create the object
// that will underlie unmarshalled instances. If not specified,
// Object.create(null) will be used.
valueConstructor: MyCustomDocument
};
Used for objects with string keys and untyped values.
const collectionProperty = {
type: 'Hash',
// optionally, you may specify configuration options for the
// @aws/dynamodb-auto-marshaller package's Marshaller class:
unwrapNumbers: false,
onInvalid: 'omit',
onEmpty: 'nullify',
};
Used for arrays or iterable objects whose elements are all of the same type.
const listOfStrings = {
type: 'List',
memberType: {type: 'String'}
};
Used for Map
objects whose values are all of the same type.
const mapOfStrings = {
type: 'Map',
memberType: {type: 'String'}
};
Used to serialize null
. Often used as a sigil value.
const nullProperty = {type: 'Null'};
Used to serialize numbers.
May be used as a table or index key.
const numberProperty = {type: 'Number'};
Used to serialize sets whose values are all of the same type. DynamoDB allows sets of numbers, sets of strings, and sets of binary values.
const binarySetProperty = {type: 'Set', memberType: 'Binary'};
const numberSetProperty = {type: 'Set', memberType: 'Number'};
const stringSetProperty = {type: 'Set', memberType: 'String'};
Used to serialize strings.
May be used as a table or index key.
const stringProperty = {type: 'String'};
Used to store arrays that have a specific length and sequence of elements.
const tupleProperty = {
type: 'Tuple',
members: [
{type: 'Boolean'},
{type: 'String'}
]
};