Principiante7 min di lettura

DynamoDB JSON e marshalling

La prima volta che leggi i dati grezzi dall'DynamoDB API, non assomiglia all'JSON inserito. Un oggetto semplice come {"status": "open", "priority": 3} ritorna come {"status": {"S": "open"}, "priority": {"N": "3"}}. Ogni valore è racchiuso in a oggetto a una chiave che ne nomina il tipo. L'avvolgimento è DynamoDB JSON e la conversione in e da ciò viene chiamato marshalling.

Questo avvolgimento è il modo in cui DynamoDB mantiene i caratteri inequivocabili sul cavo. Ma inciampa chiunque si aspetti un semplice JSON e scriverlo a mano è soggetto a errori.

Cos'è DynamoDB JSON?

DynamoDB JSON è il formato wire con tag di tipo utilizzato da DynamoDB, in cui ogni valore è racchiuso in un oggetto a chiave singola che ne denomina il tipo: {"S": "open"} per una stringa, {"N": "3"} per un numero. La conversione del semplice JSON in esso (e viceversa) è chiamata marshalling. Mantiene i tipi non ambigui, poiché il semplice JSON non può esprimere insiemi o binari e poiché i numeri DynamoDB viaggiano sul filo come stringhe, un 3 senza tag sarebbe ambiguo.

  • DynamoDB JSON contrassegna ogni valore con il suo tipo{"S": "..."} per una stringa, {"N": "..."} per un numero e così via.
  • Marshalling = semplice JSON → DynamoDB JSON. Unmarshalling = il contrario.
  • I numeri sono stringhe sul cavo{"N": "3"}, non {"N": 3} — per preservare precisione.
  • I tag type sono il sistema del tipo di dati già modellato con: S, N, B, BOOL, NULL, L, M, SS, NS, BS.
  • Non scriverlo a mano. Il client di documenti dell'SDK (o un convertitore) esegue il marshalling per tu; farlo manualmente solo durante il debug o la creazione di espressioni.

Il problema: il semplice JSON non è sufficiente

JSON ha esattamente tre tipi scalari: stringa, numero, booleano, più null, array e oggetti. DynamoDB ha di più: binario e tre tipi set (set di stringhe, set di numeri, set binario) che JSON non può esprimere affatto. E perché i numeri DynamoDB viaggiano sul filo come stringhe, un 3 senza tag sarebbe ambiguo, inoltre JSON non è in grado di distinguere un elenco da un impostare.

Quindi DynamoDB non può semplicemente memorizzare il tuo JSON così com'è: è necessario che venga dichiarato il tipo esatto di ciascun valore esplicitamente. Il descrittore del tipo è il modo in cui lo fa, senza perdite, su ogni richiesta e risposta.

Come funziona la codifica

Ogni valore di attributo diventa un oggetto a chiave singola la cui chiave è un descrittore di tipo:

DescrittoreDigitareEsempio
SStringa{"S": "open"}
NNumero (come stringa){"N": "3"}
BBinario{"B": "dGV4dA=="}
BOOLBooleano{"BOOL": true}
NULLNullo{"NULL": true}
LElenco{"L": [{"S": "a"}, {"N": "1"}]}
MMappa{"M": {"k": {"S": "v"}}}
SS / NS / BSStringa/Numero/Set binario{"SS": ["a", "b"]}

Elenchi e mappe nidificano gli stessi descrittori fino in fondo, quindi un elemento profondamente strutturato diventa profondamente avvolto. I numeri viaggiano sul filo come stringhe di proposito: lo consente DynamoDB conserva tutte le 38 cifre di precisione numerica che un numero JSON (un IEEE-754 doppio, ~15-17 cifre significative) arrotonderebbe silenziosamente. Questi sono gli stessi tipi di dati con cui modelli; DynamoDB JSON è proprio il loro esplicito modulo on-the-wire, definito nel Riferimento API di basso livello AWS.

Esempio realizzato: una voce del registro di controllo

Semplice JSON che scriveresti nella tua app:

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

Marshalled su DynamoDB JSON per API:

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

Nota le scelte dietro questo elemento: ticketId è diventato N con un valore string; tags come set di corde (SS), non come elenco, è una scelta di modellazione fatta a mano: un convertitore generico alimentato plain JSON emette L, perché viene ordinato un array JSON e può ripetere, mentre SS deduplica e non è ordinato. Se tags debba essere SS o L è a la chiamata di modellazione che il convertitore non può fare per te, ecco perché comprendere il file la codifica è importante.

Conversione in DynoTable

Raramente hai bisogno di leggerlo o scriverlo a mano. Incolla il semplice JSON nel file Convertitore DynamoDB JSON per effettuare il marshalling (e viceversa) e quando stai assemblando una richiesta, il file Generatore di espressioni DynamoDB emette correttamente mappa attributi-valori organizzata insieme all'espressione. Nell'app stessa, DynoTable mostra gli elementi come valori semplici e leggibili e li organizza per te durante la scrittura.

DynoTable mostra un elemento come valori semplici, con DynamoDB JSON grezzo disponibile.
DynoTable mostra un elemento come valori semplici, con DynamoDB JSON grezzo disponibile.

Insidie + passaggi successivi

  • I numeri sono stringhe in DynamoDB JSON{"N": "3"}. Citare è importante; non farlo emettere un numero nudo.
  • Insiemi o elenchi è una decisione di modellazione la codifica rende visibile: seleziona deliberatamente (vedere tipi di dati).
  • Preferire il client di documenti SDK rispetto allo smistamento manuale nel codice dell'app; manuale di riserva DynamoDB JSON per debug ed espressioni.
  • Sono consentite stringhe vuote per attributi non chiave (dal 2020) ma vengono comunque rifiutate per le chiavi di tabella e indice e hanno storicamente attivato gli strumenti: convalidare i casi limite.

Vuoi sfogliare gli elementi come valori semplici invece di decodificare i tag di tipo a occhio? Scarica DynoTable e lavora direttamente con i tuoi dati.

Client di basso livello rispetto a client di documenti

L'AWS SDK offre due livelli:

StratoForma di inputChi comanda
@aws-sdk/client-dynamodb (basso livello)DynamoDB JSON AttributeValue mappeIl tuo codice o helper
@aws-sdk/lib-dynamodb (documento)Oggetti JS sempliciSDK su send/receive

Il codice dell'applicazione dovrebbe essere predefinito per il client di documenti per PutItem/GetItem. Raggiungi mappe di basso livello quando crei manualmente aggiorna espressioni o quando una libreria si aspetta valori degli attributi digitati.

Anche i valori degli attributi delle espressioni vengono sottoposti a marshalling

Segnaposto ConditionExpression, UpdateExpression e FilterExpression (:val, :inc) mappano i valori sottoposti a marshalling in ExpressionAttributeValues:

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

Una mancata corrispondenza (invio di "open" senza il wrapper S sul client di basso livello) restituisce ValidationException. Il costruttore di espressioni emette la mappa a fianco la stringa dell'espressione in modo che i segnaposto e i tipi rimangano allineati.

Attributo nomi in conflitto con parole riservate utilizzare ExpressionAttributeNames (#st) invece; lo strumento di controllo restituisce l'alias mappa pronta per essere incollata.

Unmarshal sorprende nei test

Errori comuni dei test dovuti al marshalling:

  • Set vuoti — DynamoDB rifiuta SS/NS/BS vuoti; omettere l'attributo invece.
  • Float in N: invia "3.14" come una stringa, non come un numero JSON, sul cavo.
  • Binario nel nodo: Uint8Array nel client documenti; base64 in JSON grezzo.
  • Attributi non definiti: documenta le strisce client undefined; cliente di basso livello potrebbe inviare payload non validi.

Quando un Lambda registra risposte API non elaborate, incolla un elemento nel file Convertitore DynamoDB JSON in JSON normale leggibile prima di confrontarsi con gli infissi.

Impatto sulle dimensioni dell'etichettatura

Ogni wrapper di tipo aggiunge byte. Un oggetto piatto JSON suddiviso campo per campo cresce circa il 30-40% in tempo reale a seconda dei nomi degli attributi, che l’inflazione alimenta dimensione articolo e arrotondamento RCU/WCU. Mappe di grandi dimensioni con nomi di attributi brevi ammortizzano le spese generali; le piccole bandiere booleane pagano ancora i loro nomi chiave più {"BOOL":true}.

Prima di caricare in blocco gli elementi sottoposti a marshalling, controllare i byte totali nel file calcolatore della dimensione dell'articolo quindi una scrittura batch non superi inaspettatamente il limite di richiesta di 16 MB.

Le due visualizzazioni di DynoTable

L'editor degli elementi mantiene il marshalling invisibile giorno dopo giorno: modifichi valori semplici, e impegna il maresciallo all'invio. Durante il debug di un articolo di produzione copiato da Log CloudWatch, passa alla visualizzazione DynamoDB JSON per visualizzare i tag esatti, quindi torna indietro su Plain JSON per le modifiche. Le azioni di esportazione copiano entrambe le rappresentazioni per i ticket e casi di test.

Aggiornato