DynamoDB JSON ve Marshalling
DynamoDB API'sinden ilk kez ham veri okuduğunuzda, koyduğunuz JSON gibi görünmez.
{"status": "open", "priority": 3} gibi düz bir nesne,
{"status": {"S": "open"}, "priority": {"N": "3"}} olarak geri gelir. Her değer,
türünü adlandıran tek anahtarlı bir nesneye sarılır. O sarma DynamoDB JSON'dur ve
ona ve ondan dönüştürmeye marshalling denir.
Bu gürültü değildir — DynamoDB'nin türleri hat üzerinde belirsizlikten uzak tutmasının yoludur. Ama düz JSON bekleyen herkesin ayağına dolanır ve onu elle yazmak hataya açıktır.
DynamoDB JSON nedir?
DynamoDB JSON, DynamoDB'nin kullandığı tür etiketli hat formatıdır; burada her değer,
türünü adlandıran tek anahtarlı bir nesneye sarılır — bir string için {"S": "open"},
bir sayı için {"N": "3"}. Düz JSON'u ona (ve geri) dönüştürmeye marshalling denir.
Türleri belirsizlikten uzak tutar, çünkü düz JSON set'leri ya da binary'i ifade
edemez ve DynamoDB sayıları hat üzerinde string olarak gittiği için etiketsiz bir 3
belirsiz olurdu.
- DynamoDB JSON her değeri türüyle etiketler — bir string için
{"S": "..."}, bir sayı için{"N": "..."}vb. - Marshalling = düz JSON → DynamoDB JSON. Unmarshalling = tersi.
- Sayılar hat üzerinde string'dir —
{"N": "3"},{"N": 3}değil — kesinliği korumak için. - Tür etiketleri, zaten modellediğiniz veri türü sistemidir — S, N, B, BOOL, NULL, L, M, SS, NS, BS.
- Onu elle yazmayın. SDK'nın document client'ı (ya da bir dönüştürücü) senin için marshal eder; bunu yalnızca hata ayıklarken ya da ifadeler kurarken elle yapın.
Sorun: düz JSON yeterli değil
JSON'un tam olarak üç skaler türü vardır — string, sayı, boolean — artı null, diziler
ve nesneler. DynamoDB'nin daha fazlası vardır: binary ve JSON'un hiç ifade edemediği
üç set türü (string set, number set, binary set). Ve DynamoDB sayıları hat
üzerinde string olarak gittiği için, etiketsiz bir 3 belirsiz olurdu — ayrıca JSON
bir list'i bir set'ten ayırt edemez.
Bu yüzden DynamoDB JSON'unuzu olduğu gibi depolayamaz — her değerin tam türünü açıkça belirtmesi gerekir. Tür tanımlayıcısı, bunu her istek ve yanıtta kayıpsız biçimde yapmasının yoludur.
Kodlama nasıl çalışır
Her attribute değeri, anahtarı bir tür tanımlayıcısı olan tek anahtarlı bir nesne olur:
| Tanımlayıcı | Tür | Örnek |
|---|---|---|
S | String | {"S": "open"} |
N | Number (as a string) | {"N": "3"} |
B | Binary | {"B": "dGV4dA=="} |
BOOL | Boolean | {"BOOL": true} |
NULL | Null | {"NULL": true} |
L | List | {"L": [{"S": "a"}, {"N": "1"}]} |
M | Map | {"M": {"k": {"S": "v"}}} |
SS / NS / BS | String / Sayı / Binary set | {"SS": ["a", "b"]} |
List'ler ve map'ler aynı tanımlayıcıları en aşağıya kadar iç içe geçirir, bu yüzden derinlemesine yapılandırılmış bir item derinlemesine sarılmış hâle gelir. Sayılar, hat üzerinde bilinçli olarak string olarak gider — bu, bir JSON sayısının (IEEE-754 bir double, ~15–17 anlamlı basamak) sessizce yuvarlayacağı tam 38 basamak sayısal kesinliği DynamoDB'nin korumasını sağlar. Bunlar, modellediğiniz aynı veri türleridir; DynamoDB JSON sadece onların açık hat üzeri biçimidir, AWS düşük seviyeli API referansında tanımlanmıştır.
İşlenmiş örnek: bir denetim günlüğü girdisi
Uygulamanızda yazacağınız düz JSON:
{
"actor": "u-204",
"action": "ticket.close",
"ticketId": 8842,
"tags": ["billing", "urgent"],
"redacted": false
}API için DynamoDB JSON'a marshal edilmiş:
{
"actor": {"S": "u-204"},
"action": {"S": "ticket.close"},
"ticketId": {"N": "8842"},
"tags": {"SS": ["billing", "urgent"]},
"redacted": {"BOOL": false}
}Bu item'ın ardındaki seçimlere dikkat edin: ticketId, string değerli bir N
oldu; tags'in bir list değil bir string set (SS) olması, elle yapılmış bir
modelleme seçimidir — düz JSON beslenen genel bir dönüştürücü L yayar, çünkü bir
JSON dizisi sıralıdır ve tekrar edebilir, oysa SS yinelemeleri kaldırır ve
sırasızdır. tags'in SS mi yoksa L mi olması gerektiği, dönüştürücünün senin için
yapamayacağı bir modelleme kararıdır, ki bu tam olarak kodlamayı anlamanın neden önemli
olduğudur.
DynoTable'da dönüştürme
Bunu elle okumanız ya da yazmanız nadiren gerekir. Düz JSON'u DynamoDB JSON dönüştürücüsüne yapıştırarak marshal edin (ve geri) ve bir istek kurarken, DynamoDB expression builder ifadeyle birlikte doğru marshal edilmiş attribute-value haritasını yayar. Uygulamanın kendisinde DynoTable, item'ları düz, okunabilir değerler olarak gösterir ve yazma sırasında senin için marshal eder.

Tuzaklar ve sonraki adımlar
- DynamoDB JSON'da sayılar string'dir —
{"N": "3"}. Tırnak önemlidir; çıplak bir sayı yaymayın. - Set'lere karşı list'ler bir modelleme kararıdır ki kodlama onu görünür kılar — bilinçli seçin (bkz. veri türleri).
- Uygulama kodunda elle marshal etmek yerine SDK document client'ını tercih edin; elle DynamoDB JSON'u hata ayıklama ve ifadeler için ayırın.
- Boş string'ler anahtar olmayan attribute'lar için izinlidir (2020'den beri) ama tablo ve dizin anahtarları için hâlâ reddedilir ve tarihsel olarak araçların ayağına dolanmıştır — uç durumları doğrulayın.
Tür etiketlerini gözle çözmek yerine item'lara düz değerler olarak göz atmak mı istiyorsunuz? DynoTable'ı indirin ve verilerinizle doğrudan çalışın.
Düşük seviyeli client'a karşı document client
AWS SDK iki katman sunar:
| Katman | Girdi biçimi | Kim marshal eder |
|---|---|---|
@aws-sdk/client-dynamodb (düşük seviyeli) | DynamoDB JSON AttributeValue haritaları | Kodunuz ya da bir yardımcı |
@aws-sdk/lib-dynamodb (document) | Düz JS nesneleri | Gönderme/almada SDK |
Uygulama kodu, PutItem/GetItem için varsayılan olarak document client'ı
kullanmalıdır. Elle
update expression yazdığınızda ya da bir
kütüphane türlenmiş attribute değerleri beklediğinde düşük seviyeli haritalara
başvurun.
İfade attribute değerleri de marshal edilir
ConditionExpression, UpdateExpression ve FilterExpression yer tutucuları
(:val, :inc), ExpressionAttributeValues içindeki marshal edilmiş değerlere
eşlenir:
":status": {"S": "open"}
":count": {"N": "1"}Bir uyuşmazlık — düşük seviyeli client'ta S sarmalayıcısı olmadan "open"
göndermek — ValidationException döndürür.
İfade oluşturucu, haritayı ifade string'inin
yanında yayar; böylece yer tutucular ve türler hizalı kalır.
Ayrılmış kelimelerle çakışan attribute
adları ise bunun yerine ExpressionAttributeNames (#st) kullanır; denetleyici
araç, alias haritasını yapıştırmaya hazır biçimde çıkarır.
Testlerde unmarshal sürprizleri
Marshalling'den kaynaklanan yaygın test hataları:
- Boş set'ler — DynamoDB boş
SS/NS/BSdeğerlerini reddeder; attribute'u bunun yerine hiç göndermeyin. Niçinde float'lar — hat üzerinde"3.14"değerini bir JSON sayısı olarak değil, string olarak gönderin.- Node'da binary — document client'ta
Uint8Array; ham JSON'da base64. - Tanımsız attribute'lar — document client
undefineddeğerleri ayıklar; düşük seviyeli client geçersiz payload gönderebilir.
Bir Lambda ham API yanıtlarını loglarken, fixture'larla karşılaştırmadan önce bir item'ı DynamoDB JSON dönüştürücüsüne yapıştırıp okunabilir düz JSON'a çevirin.
Etiketlemenin boyut etkisi
Her tür sarmalayıcısı bayt ekler. Alan alan marshal edilmiş düz bir JSON nesnesi,
attribute adlarına bağlı olarak hat üzerinde kabaca %30–40 büyür — bu şişme
item boyutunu ve RCU/WCU yuvarlamasını besler.
Kısa attribute adlarına sahip büyük map'ler ek yükü amorti eder; minicik boolean
bayrakları ise yine de kendi anahtar adlarının ve {"BOOL":true} değerinin bedelini
öder.
Marshal edilmiş item'ları toplu yüklemeden önce toplam baytı item boyutu hesaplayıcısında kontrol edin; böylece bir batch write beklenmedik biçimde 16 MB istek sınırını aşmasın.
DynoTable'ın iki görünümü
Item editörü, marshalling'i günden güne görünmez tutar — düz değerleri düzenlersiniz ve commit'ler gönderim sırasında marshal edilir. CloudWatch loglarından kopyalanmış bir production item'ında hata ayıklarken, tam etiketleri görmek için DynamoDB JSON görünümüne geçin, sonra düzenleme için Düz JSON'a geri dönün. Dışa aktarma eylemleri, ticket'lar ve test senaryoları için her iki temsili de kopyalar.


