φυβλαςのβλογ
phyblas的博客



javascript เบื้องต้น บทที่ ๒๘: การจัดการกับ json
เขียนเมื่อ 2019/08/11 00:04
แก้ไขล่าสุด 2021/09/28 16:42


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 ได้




-----------------------------------------

囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧囧

ดูสถิติของหน้านี้

หมวดหมู่

-- คอมพิวเตอร์ >> เขียนโปรแกรม >> javascript

ไม่อนุญาตให้นำเนื้อหาของบทความไปลงที่อื่นโดยไม่ได้ขออนุญาตโดยเด็ดขาด หากต้องการนำบางส่วนไปลงสามารถทำได้โดยต้องไม่ใช่การก๊อปแปะแต่ให้เปลี่ยนคำพูดเป็นของตัวเอง หรือไม่ก็เขียนในลักษณะการยกข้อความอ้างอิง และไม่ว่ากรณีไหนก็ตาม ต้องให้เครดิตพร้อมใส่ลิงก์ของทุกบทความที่มีการใช้เนื้อหาเสมอ

目录

从日本来的名言
模块
-- numpy
-- matplotlib

-- pandas
-- manim
-- opencv
-- pyqt
-- pytorch
机器学习
-- 神经网络
javascript
蒙古语
语言学
maya
概率论
与日本相关的日记
与中国相关的日记
-- 与北京相关的日记
-- 与香港相关的日记
-- 与澳门相关的日记
与台湾相关的日记
与北欧相关的日记
与其他国家相关的日记
qiita
其他日志

按类别分日志



ติดตามอัปเดตของบล็อกได้ที่แฟนเพจ

  查看日志

  推荐日志

ตัวอักษรกรีกและเปรียบเทียบการใช้งานในภาษากรีกโบราณและกรีกสมัยใหม่
ที่มาของอักษรไทยและความเกี่ยวพันกับอักษรอื่นๆในตระกูลอักษรพราหมี
การสร้างแบบจำลองสามมิติเป็นไฟล์ .obj วิธีการอย่างง่ายที่ไม่ว่าใครก็ลองทำได้ทันที
รวมรายชื่อนักร้องเพลงกวางตุ้ง
ภาษาจีนแบ่งเป็นสำเนียงอะไรบ้าง มีความแตกต่างกันมากแค่ไหน
ทำความเข้าใจระบอบประชาธิปไตยจากประวัติศาสตร์ความเป็นมา
เรียนรู้วิธีการใช้ regular expression (regex)
การใช้ unix shell เบื้องต้น ใน linux และ mac
g ในภาษาญี่ปุ่นออกเสียง "ก" หรือ "ง" กันแน่
ทำความรู้จักกับปัญญาประดิษฐ์และการเรียนรู้ของเครื่อง
ค้นพบระบบดาวเคราะห์ ๘ ดวง เบื้องหลังความสำเร็จคือปัญญาประดิษฐ์ (AI)
หอดูดาวโบราณปักกิ่ง ตอนที่ ๑: แท่นสังเกตการณ์และสวนดอกไม้
พิพิธภัณฑ์สถาปัตยกรรมโบราณปักกิ่ง
เที่ยวเมืองตานตง ล่องเรือในน่านน้ำเกาหลีเหนือ
ตระเวนเที่ยวตามรอยฉากของอนิเมะในญี่ปุ่น
เที่ยวชมหอดูดาวที่ฐานสังเกตการณ์ซิงหลง
ทำไมจึงไม่ควรเขียนวรรณยุกต์เวลาทับศัพท์ภาษาต่างประเทศ