javascript - Bir JSON nesnesini belirli bir tipe dönüştürme
Birçok dize içeren bir JSON nesnem var...
{
id: "1",
amount: "57,000",
title: "I am a test"
}
Bunu şu şekilde bir arayüze nasıl dönüştürebilirim:
interface MyObj {
id: number;
amount: number;
title: string;
}
Her bir nesne özelliği üzerinde dönüp gerekli tipe çevirmeyi denemem mi gerekecek yoksa bir JSON nesnesini basitçe bir tipe zorla dönüştürmeyi mi deneyebilirim?
Açıklık için, işte bazı ek bilgiler.
Yukarıdaki örnek nesnelerden oluşan bir dizim var, JSON yani...
[
{
id: "1",
amount: "57,000",
title: "I am a test"
},
{
id: "2",
amount: "2347,000",
title: "I am a test as well"
}
]
Bu JSON nesnesindeki tüm değerler stringdir. TS'de nesneleri her kullandığımızda, türlerinin doğru olmasını istiyoruz. Örneğin, id ve miktar sayılar olmalıdır, bunlar duruma kaydedilmeden önce dönüştürülebilir.
Yani, yukarıdaki dizideki JSON nesnelerini belirli bir arayüz veya tipe dönüştürmek istiyorum. Türler eşleşmediği için sadece arayüzü kullanamam, bazı dönüşümler yapmam veya aslında arayüze uyum sağlamadan önce bir tipe dönüştürmeyi denemem gerekiyor. Soru şu: Dizideki JSON nesneleri üzerinde nasıl gezinip bazı anahtarları string'den numaraya dönüştürebilirim (muhtemelen)?
Cevap #1
JSON.parse yeniden canlandırıcı
JSON.parse isteğe bağlı olarak ikinci bir argüman, bir reviver fonksiyonu alabilir -
Eğer bir
reviverbelirtilmişse, çözümleme ile hesaplanan değer, geri döndürülmeden önce dönüştürülür. Özellikle, hesaplanan değer ve tüm özellikleri (en içteki özelliklerden başlayarak orijinal değerin kendisine kadar) tek tekreviverüzerinden geçirilir. Ardından, işlenen özelliği içeren nesne this olarak ve özellik adı bir dize, özellik değeri de argümanlar olarak çağrılır. Eğerreviverfonksiyonuundefineddöndürürse (veya örneğin, fonksiyonun sonuna kadar yürütme durursa herhangi bir değer döndürmezse), özellik nesneden silinir. Aksi takdirde, özellik döndürülen değer olacak şekilde yeniden tanımlanır.
function MyObject({ id, amount, title }) {
this.id = id
this.amount = amount
this.title = title
}
function reviver(key, value) {
if (value?.id && value?.amount && value?.title)
return new MyObject(value)
else
return value
}
const json =
`[{"id":"1","amount":"57,000","title":"I am a test"},{"id":"2","amount":"13,000","title":"I am also test"},{"id":"3","amount":"1,000","title":"I am a third test"},{"id":"4","amount":"200","something":"else"},1,"foo"]`
const data =
JSON.parse(json, reviver)
for (const value of data)
console.log(value)MyObject { id: '1', amount: '57,000', title: 'I am a test' }
MyObject { id: '2', amount: '13,000', title: 'I am also test' }
MyObject { id: '3', amount: '1,000', title: 'I am a third test' }
{ id: '4', amount: '200', something: 'else' }
1
foo
daha iyi yap
Yukarıdaki revive biraz kırılgan bir işlevdir. Bu nedenle, JSON.stringify edilmiş verilerinizin bir type alanı veya benzeri bir alan içermesi önerilir -
[ { type: "MyObject", ... }, { type: "Another", ... }, "foo", 1, ... ]
Şimdi reviver'ı basit bir şekilde yazabiliriz -
function reviver(key, value) {
switch (value?.type) {
case "MyObject": return MyObject(value)
case "OtherThing": return OtherThing(value)
case "Another": return Another(value)
default: return value // revive without modification
}
}
Cevap #2
TypeScript sadece bir geliştirme/derleme zamanı aracıdır; bu, as kullanmak gibi tip dönüşümünün çalışma zamanında, örneğin stringleri sayılarına dönüştürmek gibi, hiçbir etkisi olmadığı anlamına gelir. Tip dönüşümü yapmak veya as kullanmak, TypeScript'e bir değeri açıkça belirli bir tür olarak değerlendirmesini söylemenin sadece bir yoludur. Eğer bunu denerseniz:
interface MyObj {
id: number;
amount: number;
title: string;
}
const data = {
id: "1",
amount: "57,000",
title: "I am a test"
};
const ofType = data as MyObj;
...TypeScript derlenmeyecek çünkü data, türler uyuşmadığından arayüzünüzle uyumlu değil. Bunu zorlasanız bile:
const ofType = data as unknown as MyObj;
...id ve amount hâlâ string olacak ve şimdi uygulamanızda bir hataya neden oldunuz.
TypeScript, kodunuzun sağlamlığı için bir kalite güvence aracı olarak vardır; veri dönüşümü için masaya herhangi bir şey getirmez. Yani saf JavaScript'te olduğu gibi, eğer verileri bir türden diğerine dönüştürmeniz gerekiyorsa özel kod yazmanız gerekecek. Örneğin, gönderildiği gibi ayrıştırılmış bir JSON diziniz varsa:
const converted: Array<MyObj> = data.map(item => ({
id: parseInt(item.id),
amount: parseInt(item.replace(/,/g, '')),
title: item.title
}));
