Principiante5 min de lectura

DynamoDB JSON y marshalling

La primera vez que lees datos en crudo desde la API de DynamoDB, no se parecen al JSON que metiste. Un objeto normal como {"status": "open", "priority": 3} vuelve como {"status": {"S": "open"}, "priority": {"N": "3"}}. Cada valor está envuelto en un objeto de una sola clave que nombra su tipo. Ese envoltorio es DynamoDB JSON, y convertir hacia y desde él se llama marshalling.

No es ruido — es cómo DynamoDB mantiene los tipos sin ambigüedad en el cable. Pero descoloca a cualquiera que espere JSON normal, y escribirlo a mano es propenso a errores.

¿Qué es DynamoDB JSON?

DynamoDB JSON es el formato de transferencia con etiquetas de tipo que utiliza DynamoDB, donde cada valor se envuelve en un objeto de una sola clave que indica su tipo — {"S": "open"} para una cadena, {"N": "3"} para un número. Convertir JSON normal a este formato (y a la inversa) se llama marshalling. Mantiene los tipos sin ambigüedad, ya que el JSON normal no puede expresar conjuntos, binarios ni distinguir "3" de 3.

  • DynamoDB JSON etiqueta cada valor con su tipo{"S": "..."} para una cadena, {"N": "..."} para un número, y así sucesivamente.
  • Marshalling = JSON normal → DynamoDB JSON. Unmarshalling = lo inverso.
  • Los números son cadenas en el cable{"N": "3"}, no {"N": 3} — para preservar la precisión.
  • Las etiquetas de tipo son el sistema de tipos de datos con el que ya modelas: S, N, B, BOOL, NULL, L, M, SS, NS, BS.
  • No lo escribas a mano. El document client del SDK (o un conversor) hace el marshalling por ti; hazlo manualmente solo al depurar o construir expresiones.

El problema: el JSON normal no basta

JSON tiene exactamente tres clases escalares — cadena, número, booleano — más null, arrays y objetos. DynamoDB tiene más: binario, y tres tipos de conjunto (conjunto de cadenas, conjunto de números, conjunto de binarios) que JSON no puede expresar en absoluto. JSON tampoco puede distinguir una cadena "3" de un número 3, ni una lista de un conjunto.

Así que DynamoDB no puede simplemente almacenar tu JSON tal cual — necesita el tipo exacto de cada valor declarado explícitamente. El descriptor de tipo es cómo lo hace, sin pérdida, en cada petición y respuesta.

Cómo funciona la codificación

Cada valor de atributo se convierte en un objeto de una sola clave cuya clave es un descriptor de tipo:

DescriptorTipoEjemplo
SCadena{"S": "open"}
NNúmero (como cadena){"N": "3"}
BBinario{"B": "dGV4dA=="}
BOOLBooleano{"BOOL": true}
NULLNulo{"NULL": true}
LLista{"L": [{"S": "a"}, {"N": "1"}]}
MMapa{"M": {"k": {"S": "v"}}}
SS / NS / BSConjunto de cadenas / números / binarios{"SS": ["a", "b"]}

Las listas y los mapas anidan los mismos descriptores hasta el fondo, así que un elemento profundamente estructurado acaba profundamente envuelto. Los números viajan por el cable como cadenas a propósito — eso permite a DynamoDB preservar una precisión arbitraria que un número JSON (un double IEEE-754) redondearía calladamente. Estos son los mismos tipos de datos con los que modelas; DynamoDB JSON es simplemente su forma explícita en el cable, definida en la referencia de la API de bajo nivel de AWS.

Ejemplo resuelto: una entrada de registro de auditoría

El JSON normal que escribirías en tu app:

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

Con marshalling a DynamoDB JSON para la API:

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

Fíjate en las decisiones que tomó el marshaller: ticketId se convirtió en N con un valor de cadena; tags se convirtió en un conjunto de cadenas (SS), no en una lista — una decisión deliberada, porque un conjunto deduplica y no está ordenado. Si tags debería ser SS o L es una decisión de modelado que el conversor no puede tomar por ti, que es exactamente por qué importa entender la codificación.

Convertir en DynoTable

Rara vez necesitas leer o escribir esto a mano. Pega JSON normal en el conversor de DynamoDB JSON para hacerle marshalling (y de vuelta), y cuando estés montando una petición, el constructor de expresiones de DynamoDB emite el mapa de valores de atributo correctamente marshalled junto con la expresión. En la propia app, DynoTable muestra los elementos como valores normales y legibles y les hace marshalling por ti al escribir.

DynoTable mostrando un elemento como valores normales, con el DynamoDB JSON en crudo disponible.
DynoTable mostrando un elemento como valores normales, con el DynamoDB JSON en crudo disponible.

Trampas y próximos pasos

  • Los números son cadenas en DynamoDB JSON{"N": "3"}. Las comillas importan; no emitas un número desnudo.
  • Conjuntos vs listas es una decisión de modelado que la codificación hace visible — elige deliberadamente (consulta tipos de datos).
  • Prefiere el document client del SDK al marshalling a mano en el código de la app; reserva el DynamoDB JSON manual para depuración y expresiones.
  • Las cadenas vacías están permitidas en los elementos pero históricamente han descolocado a las herramientas — valida los casos límite.

¿Quieres explorar los elementos como valores normales en lugar de descodificar etiquetas de tipo a ojo? Descarga DynoTable y trabaja con tus datos directamente.

Actualizado