json คือ
ปกติเวลาใช้จาวาสคริปต์นั้นเรามักจะเก็บข้อมูลโดยเขียนเป็นข้อความโค้ดที่ใช้สร้างออบเจ็กต์
ข้อมูลแบบนี้เรียกว่า json ย่อมาจาก javascript object notation
ถ้ามีโค้ดสำหรับสร้างออบเจ็กต์อยู่
แล้วป้อนให้โปรแกรมจาวาสคริปต์ไปอ่านก็จะถูกตีความเป็นออบเจ็กต์ในจาวาสคริปต์
แล้วนำมาใช้ได้
ในจาวาสคริปต์ตั้งแต่รุ่น ES5
ได้เตรียมออบเจ็กต์ที่รวบรวมฟังก์ชันสำหรับจัดการกับข้อมูลโค้ด json
ชื่อออบเจ็กต์นั้นคือ JSON (เขียนด้วยตัวพิมพ์ใหญ่หมด)
การแปลงออบเจ็กต์เป็นโค้ด json
เมื่อมีออบเจ็กต์ที่ถูกสร้างขึ้นมาในจาวาสคริปต์แล้วต้องการเก็บข้อมูลของออบเจ็กต์นั้นสามารถทำได้โดยใช้ฟังก์ชัน
JSON.stringify
ตัวอย่าง
var pokemon = {};
pokemon.chue = "เพาเวา";
pokemon.lv = 20;
alert(JSON.stringify(pokemon));
ได้
{"chue":"เพาเวา","lv":20}
ออบเจ็กต์ที่เป็นแถวลำดับเองก็จะถูกแปลงเป็นในรูปแบบแถวลำดับ ซึ่งล้อมด้วย []
เช่น
var fung_pokemon = [];
fung_pokemon.push("โกส");
fung_pokemon.push("สลีป");
fung_pokemon.push("แครบ");
alert(JSON.stringify(fung_pokemon));
ได้
["โกส","สลีป","แครบ"]
โครงสร้างที่ซ้อนกันลึกเข้าไปอย่างอาเรย์ของออบเจ็กต์ก็แปลงได้
var fung_pokemon = [{ chue: "ลักกี", lv: 13 }];
fung_pokemon.push({ chue: "มอนจารา", lv: 14 });
fung_pokemon.push({ chue: "การูรา", lv: 15 });
alert(JSON.stringify(fung_pokemon));
ได้
[{"chue":"ลักกี","lv":13},{"chue":"มอนจารา","lv":14},{"chue":"การูรา","lv":15}]
ข้อแตกต่างระหว่าง json
กับโค้ดสร้างออบเจ็กต์ที่ใช้จริงๆในจาวาสคริปต์
แม้จะบอกว่า json คือโค้ดที่ใช้สร้างออบเจ็กต์ในจาวาสคริปต์ แต่โค้ดของ json
ก็ไม่ได้เหมือนกับโค้ดสร้างออบเจ็กต์ในจาวาสคริปต์ไปทั้งหมดเสียทีเดียว
โค้ด json นั้นมีข้อจำกัดมากกว่าเล็กน้อย ดังนี้
1. ชื่อพรอเพอร์ตีจะต้องคร่อมด้วยเครื่องหมายคำพูดเสมอ เช่นเขียน {chue:
"เพาเวา"} แบบนี้ไม่ได้
2. ใช้ตัวเลขเป็นชื่อพรอเพอร์ตีไม่ได้
3. หลังพรอเพอร์ตีตัวสุดท้ายจะลงท้ายด้วยจุลภาค , ไม่ได้ เช่นเขียน
{"chue": "เพาเวา",}
4. ข้อมูลตัวเลขจะขึ้นต้นด้วยเลข 0 ไม่ได้ เช่น {"lv": 020}
ทั้งหมดนี้เป็นแค่ข้อจำกัดจุกจิกเล็กๆน้อยๆที่เพิ่มเข้ามา
แต่โค้ดสร้างออบเจ็กต์นั้นสามารถละเครื่องหมายคำพูดได้ จะใช้ตัวเลขก็ได้
ใส่จุลภาคหลังตัวสุดท้ายได้ และขึ้นต้นตัวเลขด้วย 0 ได้ ดังที่ได้กล่าวไปไว้ใน
บทที่ ๙
เวลาที่ใช้ JSON.stringify ในการแปลง
จะถูกแปลงให้เป็นไปตามข้อจำกัดนี้โดยอัตโนมัติอยู่แล้ว จึงไม่ต้องเป็นห่วง
และโค้ดที่เขียนในแบบ JSON ก็สามารถนำมาอ่านในจาวาสคริปต์ได้แน่นอน
การใส่ฟังก์ชันจัดการข้อมูลในออบเจ็กต์เมื่อแปลงเป็นโค้ด json
เมื่อใช้ฟังก์ชัน JSON.stringify สามารถใส่อาร์กิวเมนต์ตัวที่ ๒ ลงไป
เป็นฟังก์ชันที่ต้องการให้จัดการทำอะไรบางอย่างกับค่าของข้อมูลก่อนที่จะแปลงเป็น
json
ฟังก์ชันที่ใช้นั้นจะต้องรับ พารามิเตอร์ ๒ ตัว ตัวแรกคือค่า
รูปแบบของฟังก์ชันเป็นแบบนี้
function(คีย์, ค่าพรอเพอร์ตีจริงในออบเจ็กต์) {
return ค่าพรอเพอร์ตีที่ต้องการให้ออกมา;
};
ตัวอย่างเช่น
หากต้องการให้แปลงข้อมูลที่เป็นตัวเลขเป็นสายอักขระที่เขียนเลขถึงทศนิยมตำแหน่งที่
๒ อาจเขียนแบบนี้
var pokemon = { chue: "เบโรริงกา", lv: 24 };
var f = function(k, v) {
if (typeof v === "number") {
return v.toFixed(2);
}
return v;
};
alert(JSON.stringify(pokemon, f));
ได้
{"chue":"เบโรริงกา","lv":"24.00"}
ถ้าหากค่าคืนกลับได้เป็น undefined หรือไม่มีค่าคืนกลับ ค่านั้นจะถูกข้าม
ไม่มีการบันทึก
เช่นต้องการตัดคีย์บางตัวทิ้งออกจากข้อมูลเมื่อแปลงเป็น json
var pokemon = { chue: "ไซดอน", lek: 112, lv: 44 };
var f = function(k, v) {
if (k != "lek") {
return v;
}
};
alert(JSON.stringify(pokemon, f));
แบบนี้ lek จะถูกข้ามไป
{"chue":"ไซดอน","lv":44}
การจัดช่องว่างและเว้นบรรทัดเมื่อแปลงออบเจ็กต์เป็นโค้ด json
ปกติเมื่อใช้ JSON.stringify
ข้อมูลจะถูกแปลงเป็นโค้ดที่เขียนเบียดกันให้สั้นที่สุด
แต่ว่าแบบนั้นบางทีก็ทำให้ดูยากเวลาที่ต้องการจะมาอ่านโค้ดดูด้วยตา
เพื่อความเป็นระเบียบในการจัดเก็บข้อมูล
บางครั้งจึงนิยมเขียนข้อมูลแบบมีการเว้นบรรทัดระหว่างข้อมูลและมีการร่น
ใน JSON.stringify หากใส่อาร์กิวเมนต์ตัวที่ ๓
จะเป็นตัวกำหนดรูปแบบการเว้นช่องว่างระหว่างข้อมูล
ส่วนอาร์กิวเมนต์ตัวที่ ๒ ถึงไม่ต้องการใส่ก็ต้องใส่ เพื่อให้ใส่ตัวที่ ๓ ได้
หากไม่ต้องการใส่อะไรก็ใส่เป็น null ไปได้
เช่นหากต้องการให้มีการร่นขั้นละ ๒ วรรค ก็ใส่เป็นเว้นวรรค ๒ ช่อง
เช่น
var fung_pokemon = [{ chue: "ฟรีเซอร์", lek: 144 }];
fung_pokemon.push({ chue: "ธันเดอร์", lek: 145 });
fung_pokemon.push({ chue: "ไฟร์", lek: 146 });
alert(JSON.stringify(fung_pokemon, null, " "));
ได้
[
{
"chue": "ฟรีเซอร์",
"lek": 144
},
{
"chue": "ธันเดอร์",
"lek": 145
},
{
"chue": "ไฟร์",
"lek": 146
}
]
ถ้าต้องการละก็อยากใส่อะไรก็ได้ก็ได้ แม้แต่ ๛ (โคมูตร)
alert(JSON.stringify(fung_pokemon, null, "๛"));
ได้
[
๛{
๛๛"chue": "ฟรีเซอร์",
๛๛"lek": 144
๛},
๛{
๛๛"chue": "ธันเดอร์",
๛๛"lek": 145
๛},
๛{
๛๛"chue": "ไฟร์",
๛๛"lek": 146
๛}
]
พรอเพอร์ตีที่ถูกแปลงเป็น json ได้กับไม่ได้
ไม่ใช่ว่าพรอเพอร์ตีทั้งหมดในออบเจ็กต์จะถูกแปลงเป็น json ได้หมดเมื่อใช้
JSON.stringify แต่พรอเพอร์ตีที่ enumerable เป็น false จะถูกข้าม
นอกจากนี้พรอเพอร์ตีในตัวโพรโทไทป์ก็จะถูกมองข้ามเช่นกัน
ตัวอย่าง
var pokemon = Object.create(
{ chanit: "ไฟฟ้า" },
{
chue: {
value: "เมรีป",
enumerable: true,
writable: true,
configurable: false
},
namnak: {
value: 0.6,
enumerable: false,
writable: true,
configurable: true
},
suansung: {
value: 7.8,
enumerable: true,
writable: false,
configurable: true
}
}
);
alert(JSON.stringify(pokemon));
ได้
{"chue":"เมรีป","suansung":7.8}
การแปลงจากโค้ด json เป็นออบเจ็กต์
เมื่อเราสามารถเก็บข้อมูลในรูปของโค้ด json ได้แล้ว
เราก็สามารถน้ำโค้ดมาใส่ในโปรแกรมจาวาสคริปต์เพื่อ
เพียงแต่ว่าถ้าโค้ด json นั้นรบเข้าโปรแกรมมาในรูปของสายอักขระ
จะนำมาใช้ในโปรแกรมโดยตรงไม่ได้
ที่จริงจะใช้ eval ก็ได้ ดังที่เคยแนะนำไปใน
บทที่ ๑๗
แต่โดยทั่วไปแล้ว eval เป็นวิธีที่ไม่ค่อยควรใช้นักจึงไม่แนะนำ
วิธีที่ดีที่สุดคือใช้ JSON.parse ซึ่งเป็นฟังก์ชันที่ใช้แปลงโค้ด json
เป็นออบเจ็กต์ขึ้นมา
ตัวอย่าง
var jpokemon = '["มินิริว","ฮาคุริว","ไคริว"]';
alert(JSON.parse(jpokemon)); // ได้ มินิริว,ฮาคุริว,ไคริว
var jpokemon = '{"chue":"โทเงปี","namnak":3.0,"suansung":0.3}';
var pokemon = JSON.parse(jpokemon);
alert(pokemon.chue); // ได้ โทเงปี
alert(pokemon.namnak); // ได้ 3
alert(pokemon.suansung); // ได้ 0.3
การใส่ฟังก์ชันจัดการข้อมูลที่แปลงจากโค้ด json เป็นออบเจ็กต์
เมื่อใช้ JSON.parse หากใส่อาร์กิวเมนต์ตัวที่ ๒ ลงไปต่อจากตัวสายอักขระ
จะเป็นการกำหนดฟังก์ชันที่ใช้จัดการกับข้อมูลก่อนที่จะแปลงเป็นออบเจ็กต์
ตัวอย่าง เช่นเปลี่ยนข้อมูลตัวเลขให้เป็นเลขไทยโดยมีทศนิยม ๒ ตำแหน่ง
var jpokemon = '{"chue":"ชอนชี","lek":170,"namnak":12.0,"suansung":0.5}';
var f = function(k, v) {
if (typeof v === "number") {
v = v.toFixed(2).replace(/\d/g, function(d) {
return "๐๑๒๓๔๕๖๗๘๙"[d];
});
if (k == "namnak") v += " กิโลกรัม";
else if (k == "suansung") v += " เมตร";
return v;
}
return v;
};
var pokemon = JSON.parse(jpokemon, f);
alert(pokemon.chue); // ได้ ชอนชี
alert(pokemon.namnak); // ได้ ๑๒.๐๐ กิโลกรัม
alert(pokemon.suansung); // ได้ ๐.๕๐ เมตร
alert(pokemon.lek); // ได้ ๑๗๐.๐๐
การคัดลอกออบเจ็กต์
ประโยชน์อีกอย่างของการใช้ JSON.parse กับ JSON.stringify ก็คือ
ใช้ในการคัดลอกออบเจ็กต์
ปกติแล้วเวลามีตัวแปรที่เก็บออบเจ็กต์อยู่ แล้วเอาตัวแปรอีกตัวมารับออบเจ็กต์นั้น
ตัวแปรทั้ง ๒ ตัวจะกลายเป็นออบเจ็กต์ตัวเดียวกัน
เวลาเปลี่ยนแปลงก็จะเปลี่ยนไปด้วยกันทั้งคู่
เรื่องนี้ได้มีอธิบายไปใน
บทที่ ๙
แต่ว่าหากต้องการที่จะคัดลอกออบเจ็กต์ใหม่ให้ได้ออบเจ็กต์ที่เหมือนออบเจ็กต์เดิมแต่ถือเป็นอีกออบเจ็กต์
แบบนี้สามารถใช้วิธีการแปลงข้อมูลเป็น json โดยใช้ JSON.stringify
จากนั้นก็แปลงกลับโดยใช้ JSON.parse แบบนี้ข้อมูลก็จะถูกสร้างขึ้นใหม่
ตัวอย่าง
var pk1 = { chue: "เนตี", lv: 20 };
var pk2 = pk1; // ป้อนตัวออบเจ็กต์ให้โดยตรง
pk2.chue = "เนตีโอ";
alert(pk1.chue); // ได้ เนตีโอ
pk1.lv = 32;
alert(pk2.lv); // ได้ 32
var pk3 = JSON.parse(JSON.stringify(pk1)); // แปลงเป็น json แล้วสร้างออบเจ็กต์ใหม่
pk3.chue = "เนติวิทย์";
alert(pk1.chue); // ได้ เนตีโอ
pk1.lv = 99;
alert(pk3.lv); // ได้ 32
ในที่นี้ ป้อนออบเจ็กต์จากตัวแปร pk1 ให้ตัวแปร pk2 โดยตรง
ดังนั้นจึงกลายเป็นออบเจ็กต์เดียวกัน
เมื่อมีการเปลี่ยนแปลงก็จะเปลี่ยนไปด้วยกัน
ส่วน pk3 นั้นสร้างขึ้นมาใหม่โดยแปลงจาก json ที่ได้จาก pk1 อีกที
ดังนั้นจึงได้ข้อมูลที่เหมือนกับ pk1
แต่เมื่อทำการเปลี่ยนแปลงใดๆก็จะไม่เปลี่ยนไปด้วยกัน
เป็นออบเจ็กต์ตัวใหม่คนละตัวกันโดยสมบูรณ์
ทิ้งท้ายบท
ที่จริงปกติโค้ด json มักถูกบันทึกเป็นลงไฟล์ เป็นไฟล์สกุล .json
และปกติเราจะอ่าน json จากไฟล์หรือดึงข้อมูลมาจากเว็บ
แต่ที่อธิบายไปในบทนี้แค่บอกว่าถ้ามีโค้ด json
ในรูปสายอักขระอยู่แล้วจะเอามาแปลงเป็นออบเจ็กต์อย่างไร
รวมถึงไม่ได้บอกวิธีที่จะนำโค้ด json ในสายอักขระมาบันทึกเก็บลงไฟล์ด้วย
ที่จริงเรื่องการอ่านเขียนไฟล์เป็นเรื่องใหญ่เรื่องหนึ่งที่สำคัญ
เพียงแต่วิธีการมีความหลากหลายแตกต่างกันไปมาก
ขึ้นอยู่กับว่าใช้จาวาสคริปต์ในไหนทำอะไรด้วย
จึงไม่ได้เขียนถึงรวมไว้ในบทเรียนนี้
ถ้าสามารถอ่านข้อความที่เป็น json จากไฟล์มา ก็สามารถใช้ JSON.parse
เพื่อแปลงเป็นข้อมูลออบเจ็กต์ได้ และถ้าเขียนข้อความได้ ก็เอาสายอักขระที่ใส่โค้ด
json ที่ได้จาก JSON.stringify มาบันทึกเป็นข้อมูล json ได้