分享 5 個(gè) JSON 相關(guān)的常用小技巧

關(guān)于 JavaScript的JSON的一些小技巧
1、格式化
默認(rèn)的字符串化器還會縮小 JSON,看起來很難看
const?user?=?{
??name:?'John',
??age:?30,
??isAdmin:?true,
??friends:?['Bob',?'Jane'],
??address:?{
????city:?'New?York',
????country:?'USA'
??}
};
console.log(JSON.stringify(user));
//=>?{"name":"John","age":30,"isAdmin":true,"friends":["Bob","Jane"],"address":{"city":"New?York","country":"USA"}}
JSON.stringify也有一個(gè)內(nèi)置的格式化程序!
console.log(JSON.stringify(user,?null,?2));
//?{
//???"name":?"John",
//???"age":?30,
//???"isAdmin":?true,
//???"friends":?[
//?????"Bob",
//?????"Jane"
//???],
//???"address":?{
//?????"city":?"New?York",
//?????"country":?"USA"
//???}
//?}
(如果你想知道那個(gè) null 是什么,我們稍后會談到)
在此示例中,JSON 格式為 2 個(gè)縮進(jìn)空格。
我們還可以指定用于縮進(jìn)的自定義字符。
console.log(JSON.stringify(user,?null,?'lol'));
//?{
//?lol"name":?"John",
//?lol"age":?30,
//?lol"isAdmin":?true,
//?lol"friends":?[
//?lollol"Bob",
//?lollol"Jane"
//?lol],
//?lol"address":?{
//?lollol"city":?"New?York",
//?lollol"country":?"USA"
//?lol}
//?}
2、隱藏字符串化數(shù)據(jù)中的某些屬性
JSON.stringify第二個(gè)參數(shù),這在很大程度上是未知的。它被稱為replacer,它是一個(gè)函數(shù)或數(shù)組,用于決定哪些數(shù)據(jù)保留在輸出中,哪些不保留。
這是一個(gè)簡單的示例,我們可以在其中隱藏password用戶。
const?user?=?{
??name:?'John',
??password:?'12345',
??age:?30
};
console.log(JSON.stringify(user,?(key,?value)?=>?{
????if?(key?===?'password')?{
????????????return;
????}
????return?value;
}));
這是輸出:
{"name":"John","age":30}
我們可以進(jìn)一步重構(gòu):
function?stripKeys(...keys)?{
????return?(key,?value)?=>?{
????????if?(keys.includes(key))?{
????????????return;
????????}
????????return?value;
????};
}
const?user?=?{
??name:?'John',
??password:?'12345',
??age:?30,
??gender:?'male'
};
console.log(JSON.stringify(user,?stripKeys('password',?'gender')))
輸出:
{"name":"John","age":30}
還可以傳遞一個(gè)數(shù)組來僅獲取某些鍵:
const?user?=?{
????name:?'John',
????password:?'12345',
????age:?30
}
console.log(JSON.stringify(user,?['name',?'age']))
輸出相同的東西。
這也適用于數(shù)組。如果你有一大堆蛋糕:
const?cakes?=?[
????{
????????name:?'Chocolate?Cake',
????????recipe:?[
????????????'Mix?flour,?sugar,?cocoa?powder,?baking?powder,?eggs,?vanilla,?and?butter',
????????????'Mix?in?milk',
????????????'Bake?at?350?degrees?for?1?hour',
????????????//?...
????????],
????????ingredients:?['flour',?'sugar',?'cocoa?powder',?'baking?powder',?'eggs',?'vanilla',?'butter']
????},
????//?tons?of?these
];
我們可以輕松地做同樣的事情,并且替換器將應(yīng)用于每個(gè)蛋糕:
const?cakes?=?[
????{
????????name:?'Chocolate?Cake',
????????recipe:?[
????????????'Mix?flour,?sugar,?cocoa?powder,?baking?powder,?eggs,?vanilla,?and?butter',
????????????'Mix?in?milk',
????????????'Bake?at?350?degrees?for?1?hour',
????????????//?...
????????],
????????ingredients:?['flour',?'sugar',?'cocoa?powder',?'baking?powder',?'eggs',?'vanilla',?'butter']
????},
????//?tons?of?these
];
console.log(JSON.stringify(cakes,?['name']))
我們得到這個(gè):
[{"name":"Chocolate Cake"},{"name":"Vanilla Cake"},...]
3、使用toJSON創(chuàng)建自定義輸出格式
如果一個(gè)對象實(shí)現(xiàn)了該toJSON函數(shù),JSON.stringify將使用它來對數(shù)據(jù)進(jìn)行字符串化。
考慮一下:
class?Fraction?{
??constructor(n,?d)?{
????this.numerator?=?n;
????this.denominator?=?d;
??}
}
console.log(JSON.stringify(new?Fraction(1,?2)))
這將輸出{"numerator":1,"denominator":2}. 但是如果我們想用一個(gè)字符串替換它1/2呢?
進(jìn)入toJSON
class?Fraction?{
??constructor(n,?d)?{
????this.numerator?=?n;
????this.denominator?=?d;
??}
??toJSON()?{
??????return?`${this.numerator}/${this.denominator}`
??}
}
console.log(JSON.stringify(new?Fraction(1,?2)))
JSON.stringify尊重toJSON財(cái)產(chǎn)和產(chǎn)出"1/2"。
4、恢復(fù)數(shù)據(jù)
我們上面的分?jǐn)?shù)示例效果很好。但是如果我們想恢復(fù)數(shù)據(jù)呢?當(dāng)我們再次解析 JSON 時(shí),如果分?jǐn)?shù)能神奇地返回,那不是很酷嗎?我們可以!
進(jìn)入復(fù)活者!
class?Fraction?{
??constructor(n,?d)?{
????this.numerator?=?n;
????this.denominator?=?d;
??}
??toJSON()?{
??????return?`${this.numerator}/${this.denominator}`
??}
??static?fromJSON(key,?value)?{
????if?(typeof?value?===?'string')?{
????????const?parts?=?value.split('/').map(Number);
????????if?(parts.length?===?2)?return?new?Fraction(parts);
????}
????return?value;
??}
}
const?fraction?=?new?Fraction(1,?2);
const?stringified?=?JSON.stringify(fraction);
console.log(stringified);
//?"1/2"
const?revived?=?JSON.parse(stringified,?Fraction.fromJSON);
console.log(revived);
//?Fraction?{?numerator:?1,?denominator:?2?}
我們可以傳遞第二個(gè)參數(shù)JSON.parse來指定 reviver 函數(shù)。恢復(fù)器的工作是將字符串化數(shù)據(jù)“恢復(fù)”回其原始形式。在這里,我們傳遞了一個(gè) reviver,它是類的靜態(tài)fromJSON屬性Fraction。
在這種情況下,reviver 檢查該值是否是一個(gè)有效的分?jǐn)?shù),如果是,它會創(chuàng)建一個(gè)新Fraction對象并返回它。
有趣的事實(shí):此功能用于內(nèi)置的 Date 對象。嘗試查找Date.prototype.toJSON
這就是為什么它有效:
console.log(JSON.stringify(new?Date()))
//=>?'"2022-03-01T06:28:41.308Z"'
要恢復(fù)日期,我們可以使用JSON.parse:
function?reviveDate(key,?value)?{
????const?regex?=?/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{1,}|)Z$/;
????if?(typeof?value?===?"string"?&&?regex.test(value))?{
????????return?new?Date(value);
????}
????return?value;
}
console.log(JSON.parse('"2022-03-01T06:28:41.308Z"',?reviveDate))
//=>?Tue?Mar?01?2022?06:28:41?GMT-0700?(Pacific?Daylight?Time)
5、使用revivers隱藏?cái)?shù)據(jù)
與解析器一樣,恢復(fù)器也可用于隱藏?cái)?shù)據(jù)。它以相同的方式工作。
這是一個(gè)例子:
const?user?=?JSON.stringify({
??name:?'John',
??password:?'12345',
??age:?30
});
console.log(JSON.parse(user,?(key,?value)?=>?{
????if?(key?===?'password')?{
????????????return;
????}
????return?value;
}));
這是輸出:
{ name: 'John', age: 30 }
譯者:JenK
譯文:https://segmentfault.com/a/1190000041488147
原文:https://dev.to/siddharthshyniben/5-secret-features-of-json-you-didnt-know-about-5bbg
- EOF -
