Iniciante7 min de leitura

DynamoDB JSON e Marshalling

A primeira vez que você lê dados brutos do DynamoDB API, ele não se parece com o JSON você coloca. Um objeto simples como {"status": "open", "priority": 3} retorna como {"status": {"S": "open"}, "priority": {"N": "3"}}. Cada valor é envolvido em um objeto de uma chave nomeando seu tipo. Esse empacotamento é DynamoDB JSON e a conversão para e a partir dele é chamado marshalling.

Esse empacotamento é como o DynamoDB mantém os tipos inequívocos na transmissão. Mas tropeça qualquer um que espera um JSON simples, e escrevê-lo à mão é propenso a erros.

O que é DynamoDB JSON?

DynamoDB JSON é o formato de ligação com etiqueta de tipo que o DynamoDB usa, onde cada valor é agrupado em um objeto de uma chave que nomeia seu tipo - {"S": "open"} para uma string, {"N": "3"} para um número. A conversão do JSON simples para ele (e vice-versa) é chamada de empacotamento. Ele mantém os tipos inequívocos, uma vez que o JSON simples não pode expressar conjuntos ou binários, e como os números do DynamoDB circulam como strings, um 3 não marcado seria ambíguo.

  • DynamoDB JSON marca cada valor com seu tipo{"S": "..."} para uma string, {"N": "..."} para um número e assim por diante.
  • Marshalling = JSON simples → DynamoDB JSON. Desempacotamento = o inverso.
  • Números são strings no fio{"N": "3"}, não {"N": 3} — para preservar precisão.
  • As tags de tipo são o sistema de tipo de dados que você já modela com: S, N, B, BOOL, NULO, L, M, SS, NS, BS.
  • Não escreva à mão. O cliente de documento do SDK (ou um conversor) empacota para você; faça isso manualmente apenas ao depurar ou construir expressões.

O problema: JSON simples não é suficiente

JSON tem exatamente três tipos escalares - string, número, booleano - mais nulo, array e objetos. O DynamoDB tem mais: binário e três tipos de set (conjunto de strings, conjunto de números, conjunto binário) que o JSON não consegue expressar. E porque os números DynamoDB andam na linha como strings, um 3 não marcado seria ambíguo - além disso, o JSON não consegue diferenciar uma lista de um definido.

Portanto, o DynamoDB não pode simplesmente armazenar seu JSON como está - ele precisa do tipo exato de cada valor declarado explicitamente. O descritor de tipo é como ele faz isso, sem perdas, em todas as solicitações e resposta.

Como funciona a codificação

Cada valor de atributo se torna um objeto de chave única cuja chave é um descritor de tipo:

DescritorTipoExemplo
SCorda{"S": "open"}
NNúmero (como uma string){"N": "3"}
BBinário{"B": "dGV4dA=="}
BOOLBooleano{"BOOL": true}
NULLNulo{"NULL": true}
LLista{"L": [{"S": "a"}, {"N": "1"}]}
MMapa{"M": {"k": {"S": "v"}}}
SS/NS/BSString/Número/Conjunto binário{"SS": ["a", "b"]}

Listas e mapas aninham os mesmos descritores em todo o caminho, portanto, um item profundamente estruturado fica profundamente embrulhado. Os números andam no fio como cordas de propósito - isso permite O DynamoDB preserva seus 38 dígitos completos de precisão numérica que um número JSON (um IEEE-754 duplo, ~15–17 dígitos significativos) seria arredondado silenciosamente. Estes são os mesmos tipos de dados com os quais você modela; DynamoDB JSON é apenas o seu explícito forma on-the-wire, definida no Referência API de baixo nível AWS.

Exemplo resolvido: uma entrada de log de auditoria

JSON simples que você escreveria em seu aplicativo:

{
  "actor": "u-204",
  "action": "ticket.close",
  "ticketId": 8842,
  "tags": ["billing", "urgent"],
  "redacted": false
}

Marshallado para DynamoDB JSON para o API:

{
  "actor": {"S": "u-204"},
  "action": {"S": "ticket.close"},
  "ticketId": {"N": "8842"},
  "tags": {"SS": ["billing", "urgent"]},
  "redacted": {"BOOL": false}
}

Observe as opções por trás deste item: ticketId tornou-se N com um valor string; tags como um conjunto de cordas (SS), não uma lista, é uma escolha de modelagem feita à mão - um conversor genérico alimentado por JSON simples emite L, porque uma matriz JSON é ordenada e pode repita, enquanto o SSdesduplica e é desordenado. Setagsdeve serSSouL é uma questão chamada de modelagem que o conversor não pode fazer para você, e é exatamente por isso que entender o a codificação é importante.

Convertendo em DynoTable

Você raramente precisa ler ou escrever à mão. Cole o JSON simples no Conversor DynamoDB JSON para empacotá-lo (e vice-versa), e quando você está montando uma solicitação, o Construtor de expressão DynamoDB emite corretamente mapa de valor de atributo organizado ao lado da expressão. No próprio aplicativo, DynoTable mostra os itens como valores simples e legíveis e os organiza para você na gravação.

DynoTable mostrando um item como valores simples, com o DynamoDB JSON bruto disponível.
DynoTable mostrando um item como valores simples, com o DynamoDB JSON bruto disponível.

Armadilhas + próximos passos

  • Números são strings em DynamoDB JSON{"N": "3"}. Citando assuntos; não emitir um número simples.
  • Conjuntos versus listas é uma decisão de modelagem que a codificação torna visível - escolha deliberadamente (consulte tipos de dados).
  • Prefira o cliente de documento SDK em vez do empacotamento manual no código do aplicativo; manual de reserva DynamoDB JSON para depuração e expressões.
  • Sequências de caracteres vazias são permitidas para atributos não-chave (desde 2020), mas ainda rejeitadas para chaves de tabela e índice e têm ferramentas historicamente desarmadas - validar casos extremos.

Quer navegar pelos itens como valores simples em vez de decodificar tags de tipo a olho nu? Baixe DynoTable e trabalhe diretamente com seus dados.

Cliente de baixo nível vs cliente de documento

O SDK AWS oferece duas camadas:

CamadaForma de entradaQuem comanda
@aws-sdk/client-dynamodb (baixo nível)DynamoDB JSON Mapas AttributeValueSeu código ou auxiliar
@aws-sdk/lib-dynamodb (documento)Objetos JS simplesSDK no send/receive

O código do aplicativo deve ser padronizado para o cliente de documento para PutItem/GetItem. Alcance mapas de baixo nível ao criar manualmente expressões de atualização ou quando uma biblioteca espera valores de atributos digitados.

Os valores dos atributos de expressão também são organizados

Espaços reservados ConditionExpression, UpdateExpression e FilterExpression (:val, :inc) mapeia para valores empacotados em ExpressionAttributeValues:

":status": {"S": "open"}
":count": {"N": "1"}

Uma incompatibilidade — enviando "open" sem o wrapper S no cliente de baixo nível — retorna ValidationException. O construtor de expressão emite o mapa ao lado a string de expressão para que os espaços reservados e os tipos permaneçam alinhados.

Atribuir nomes que colidem com palavras reservadas usar ExpressionAttributeNames (#st); a ferramenta verificador gera o alias mapa pronto para colar.

Unmarshal surpreende nos testes

Falhas comuns em testes de triagem:

  • Conjuntos vazios — DynamoDB rejeita SS/NS/BS vazios; omitir o atributo em vez disso.
  • Flutua em N — envia "3.14" como uma string, não um número JSON, na transmissão.
  • Binário no NodeUint8Array no cliente de documento; base64 em JSON bruto.
  • Atributos indefinidos — tiras de clientes do documento undefined; cliente de baixo nível pode enviar cargas inválidas.

Quando um Lambda registra respostas API brutas, cole um item no arquivo Conversor DynamoDB JSON para JSON simples legível antes de comparar com os fixtures.

Impacto do tamanho da marcação

Cada wrapper de tipo adiciona bytes. Um objeto plano JSON organizado campo por campo cresce cerca de 30-40% na transferência, dependendo dos nomes dos atributos - que a inflação alimenta tamanho do item e arredondamento RCU/WCU. Mapas grandes com nomes de atributos curtos amortizam despesas gerais; pequenas bandeiras booleanas ainda pagam seus nomes principais mais {"BOOL":true}.

Antes de carregar itens empacotados em massa, verifique o total de bytes no calculadora de tamanho de item então uma gravação em lote não ultrapassa inesperadamente o limite de solicitação de 16 MB.

Duas visualizações do DynoTable

O editor de itens mantém a organização invisível dia após dia - você edita valores simples, e compromete o marechal no envio. Ao depurar um item de produção copiado de Logs do CloudWatch, alterne para a visualização DynamoDB JSON para ver as tags exatas e depois volte para Plain JSON para edições. As ações de exportação copiam qualquer representação para tickets e casos de teste.

Atualizado