JSON Key Sorter: เรียง key ใน JSON แบบ recursive เพื่อ diff และ snapshot test ที่นิ่งเสมอ
เรียง key ใน JSON ทุกระดับแบบ recursive ด้วยเครื่องมือออนไลน์ JSON Key Sorter ฟรี เลือกเรียงตามตัวอักษร แบบ case-sensitive หรือตาม value type เพื่อ stable diff และ snapshot test ที่เชื่อถือได้
Table of Contents
นักพัฒนาที่ทำงานกับ JSON ทุกคนเคยเจอปัญหาเดียวกัน นั่นคือข้อมูลสองชุดที่มีเนื้อหาเหมือนกันทุกอย่างกลับไม่ match กัน เพราะ key เรียงอยู่ในลำดับที่ต่างกัน แม้ข้อกำหนดของ JSON จะระบุชัดเจนว่าลำดับของ key ภายใน object ไม่มีความหมาย แต่เครื่องมือเกือบทุกตัวที่จับกับข้อความ JSON ตั้งแต่ git diff ไปจนถึง snapshot testing framework กลับมองว่าการสลับลำดับ key เป็นการเปลี่ยนแปลงที่เกิดขึ้นจริง JSON Key Sorter บน Online Tools Forge แก้ปัญหานี้ได้ในไม่กี่วินาที เพียงวาง JSON ของคุณลงไป เครื่องมือจะเรียง key ในทุก object แบบ recursive เข้าสู่ลำดับมาตรฐานที่คาดเดาได้เสมอ
เนื่องจากเครื่องมือทำงานทั้งหมดในเบราว์เซอร์ ข้อมูลที่คุณวางจึงไม่ถูกอัปโหลดไปไหนเลย ทำให้ใช้กับ API response ภายในองค์กร ไฟล์ config หรือข้อมูลอื่น ๆ ที่ไม่อยากแชร์ออกไปได้อย่างปลอดภัย คุณได้ทั้งการเรียงตามตัวอักษรพร้อมโหมด case-sensitive การเรียงตามชนิดข้อมูล (value type) ทิศทางจากน้อยไปมากหรือมากไปน้อย และ indentation ที่ปรับได้หลายระดับ ตั้งแต่ 2 หรือ 4 ช่องว่างขึ้นไป เพื่อให้ผลลัพธ์ตรงกับสไตล์การจัดรูปแบบของโปรเจกต์คุณพอดี
ในบทความนี้ เราจะดูกันว่าทำไม JSON ที่ deterministic จึงสำคัญ สาธิตวิธีใช้เครื่องมือทีละขั้นตอน และพูดถึง workflow ยอดนิยมที่เครื่องมือนี้ช่วยประหยัดเวลาได้มากที่สุด ทั้ง snapshot test การเปรียบเทียบไฟล์ config และการทำ canonical hash
ทำไมต้องใช้ JSON Key Sorter?
- Diff ที่นิ่งสำหรับ snapshot test. เมื่อ key ถูกเรียงออกมาในลำดับเดิมเสมอ ไฟล์ snapshot จะไม่ fail ด้วยเหตุผลที่ไม่สำคัญอีกต่อไป และทุก test ที่แดงจะชี้ไปที่การเปลี่ยนแปลงของข้อมูลจริง ๆ ไม่ใช่แค่เรื่องลำดับ
- Review config ที่มีความหมาย. การเรียงทั้งสองไฟล์ก่อนเปรียบเทียบทำให้ diff แสดงเฉพาะค่าที่เปลี่ยนไปจริง ไม่ใช่บรรทัดที่แค่ย้ายตำแหน่งไปมา
- Canonical JSON สำหรับ hashing. ถ้าคุณ hash JSON เพื่อทำ cache key ตรวจจับการเปลี่ยนแปลง หรือเซ็นข้อมูล key ที่เรียงแล้วรับประกันว่าข้อมูลเดียวกันจะให้ hash เดียวกันเสมอ
- ไฟล์ที่อ่านง่ายขึ้นชัดเจน. key ที่เรียงตามตัวอักษรทำให้เอกสาร JSON ขนาดใหญ่สแกนและค้นหาด้วยตาได้ง่ายขึ้นอย่างมีนัยสำคัญ
- เรียงแบบ recursive ทุกระดับ. เครื่องมือเรียง object ในทุกระดับความลึก ทำให้ payload ที่ซ้อนกันลึกออกมาเป็น canonical เต็มรูปแบบ ไม่ใช่เก็บงานแค่ชั้นบนสุด
- ไม่ต้องติดตั้ง ไม่มีความเสี่ยง. ทุกอย่างเกิดขึ้นฝั่ง client ในเบราว์เซอร์ของคุณ ไม่มีบัญชี ไม่มีการอัปโหลด ไม่มี telemetry
ฟีเจอร์หลัก
| ฟีเจอร์ | สิ่งที่ทำ |
|---|---|
| เรียง key แบบ recursive | จัดลำดับ key ในทุกระดับการซ้อน รวมถึง object ที่อยู่ภายใน array |
| เรียงตามตัวอักษร (alphabetical) | จัด key จาก A ถึง Z เพื่อให้ข้อมูลเดียวกัน serialize ออกมาเหมือนกันทุกครั้ง |
| ตัวเลือก case-sensitive | เรียงตัวพิมพ์ใหญ่และตัวพิมพ์เล็กอย่างเคร่งครัด (เช่น URL มาก่อน url) |
| เรียงตามชนิดข้อมูล | จัดกลุ่ม key ตามชนิดของ value แทนการเรียงตามชื่อ key |
| จากน้อยไปมากหรือมากไปน้อย | สลับทิศทางการเรียงทั้งหมดได้ด้วยการกดเพียงครั้งเดียว |
| Indentation ปรับได้ | เลือก 2 ช่องว่าง 4 ช่องว่าง หรือค่าอื่นให้ตรงกับ style guide ของทีม |
| ผลลัพธ์นิ่งและทำซ้ำได้ | อินพุตและการตั้งค่าชุดเดิมให้ผลลัพธ์แบบ byte-for-byte ที่เหมือนกันเสมอ |
| ทำงานในเบราว์เซอร์ | ประมวลผลฝั่ง client ล้วน ๆ ข้อมูลของคุณจึงไม่มีวันออกจากเครื่อง |
จุดที่ควรรู้เพิ่มเติมมีอยู่บ้าง พฤติกรรมแบบ recursive คือจุดต่างที่แท้จริง เพราะเครื่องมือออนไลน์หลายตัวเรียงเฉพาะ object ชั้นบนสุดแล้วทิ้งความรกไว้ในโครงสร้างที่ซ้อนอยู่ข้างใน ตัวเลือก case-sensitive สำคัญเมื่อมี key ตัวพิมพ์ปนกันอยู่ใน schema เดียวกัน เช่น ID กับ id เพราะการเรียงแบบเคร่งครัดทำให้ตำแหน่งของมันชัดเจนและทำซ้ำได้เสมอ ส่วนการเรียงตาม value type จะให้ layout อีกแบบหนึ่งที่นิ่งไม่แพ้กัน ซึ่งบางทีมชอบนำไปใช้กับไฟล์ config เพราะ field ที่จัดกลุ่มตามชนิดอ่านรวดเร็วกว่าการสลับปนกันไปมา
วิธีใช้งาน JSON Key Sorter
- วาง JSON ของคุณ. นำ payload ไฟล์ config หรือ API response มาวางในช่องอินพุต ถ้า JSON ไม่ถูกต้องตามรูปแบบ เครื่องมือจะแจ้งปัญหาทันทีเพื่อให้คุณแก้ไขก่อนทำการเรียง
- เลือกโหมดและทิศทางการเรียง. เลือกเรียงตามตัวอักษร (เปิด case-sensitive ถ้าต้องการลำดับตัวอักษรแบบเคร่งครัด) หรือเรียงตาม value type จากนั้นเลือกทิศทางจากน้อยไปมากหรือมากไปน้อย
- ตั้งค่า indentation. ปรับให้ตรงกับรูปแบบปลายทาง: 2 ช่องว่างเป็นค่าเริ่มต้นยอดนิยมบนเว็บ 4 ช่องว่างเหมาะกับ style guide จำนวนมาก และยังมีความกว้างอื่นให้เลือกอีกด้วย
- กด Sort. เครื่องมือจะเดินไล่ทุก object ในเอกสารแบบ recursive แล้วสร้างผลลัพธ์ใหม่โดยเรียง key ตามที่คุณเลือก โดยไม่แตะต้องค่า (value) ใด ๆ เลย
- คัดลอกผลลัพธ์ที่นิ่ง. นำผลลัพธ์ไปวางในไฟล์ snapshot config หรือ pipeline ได้อย่างมั่นใจ เพราะอินพุตชุดเดิมจะสร้างข้อความชุดเดิมออกมาทุกครั้ง
ทำไม Deterministic JSON จึงสำคัญ
ข้อกำหนดของ JSON นิยาม object ว่าเป็นชุดของคู่ name/value ที่ไม่มีลำดับ ข้อมูลสองชุดที่มี key และ value เหมือนกันจึงเหมือนกันในเชิงความหมาย แม้ key จะอยู่ในตำแหน่งต่างกันก็ตาม ตัวอย่างเช่น {"a":1,"b":2} เท่ากับ {"b":2,"a":1} ในฐานะข้อมูล ปัญหาเริ่มต้นในวินาทีที่ข้อมูลนั้นกลายเป็นข้อความ เพราะ diff, version control, snapshot test และ hash function ล้วนทำงานกับสตริงที่ serialize แล้ว ซึ่งลำดับของ key มองเห็นได้ชัดเท่ากับ value ทุกตัวในนั้น
นี่คือเหตุผลที่การสลับลำดับเพียงเพื่อความสวยงามสามารถทำให้ build พังได้ framework อย่าง Jest หรือ Vitest เก็บ JSON ที่ serialize แล้วของ response ไว้และเปรียบเทียบใหม่ทุกครั้งที่รัน ถ้า backend เปลี่ยนลำดับการ serialize snapshot จะ fail ทันทีทั้งที่ข้อมูลไม่ได้เปลี่ยนแปลงอะไรเลย การ hashing ก็ทำงานในลักษณะเดียวกัน hash สองตัวที่คำนวณจาก JSON คนละลำดับจะไม่ match กันเลยแม้แต่ตัวเดียว ซึ่งกระทบไปถึง cache key การตรวจจับการเปลี่ยนแปลง และระบบ signature ที่สร้างทับข้อมูลเหล่านี้
ผลลัพธ์ที่ deterministic ต้องอาศัยการเรียงแบบ recursive การเรียงเฉพาะชั้นบนสุดแก้ปัญหาไม่ได้ เพราะความรกที่แท้จริงใน payload มักซ่อนอยู่ใน object ที่ซ้อนอยู่ใน array ที่ซ้อนอยู่ใน object อีกที เครื่องมือที่เดินไล่ทั้งต้นไม้ข้อมูลและใช้กฎการเรียงเดียวกันทุกตำแหน่งจะให้ผลลัพธ์ที่ canonical ครบทุกระดับ ซึ่งเป็นสิ่งที่ทำให้การเปรียบเทียบไว้วางใจได้
สิ่งที่สำคัญไม่แพ้กันคือ array ต้องไม่ถูกแตะ array ใน JSON มีลำดับโดยนิยาม [1,2,3] ไม่ใช่ [3,2,1] key sorter ที่ถูกต้องจึงจัดลำดับเฉพาะ key ของ object เท่านั้น และคงลำดับสมาชิกใน array ไว้เป๊ะทุกตำแหน่ง นั่นคือเส้นแบ่งที่ชัดเจนระหว่างการทำ canonicalization กับการทำให้ข้อมูลเสียหาย
สุดท้าย กฎการเรียงที่คุณเลือกจะกลายเป็นส่วนหนึ่งของธรรมเนียมการทำงานของทีม การเรียงตามตัวอักษรธรรมดาเป็นค่าเริ่มต้นที่ง่ายและนิยมที่สุด การเรียงแบบ case-sensitive ขจัดความกำกวมเมื่อ key ตัวพิมพ์ปนกัน และการเรียงตาม value type ให้ layout แบบจัดกลุ่มที่บางทีมชอบนำไปใช้กับไฟล์ config ไม่ว่าจะเลือกแบบไหน หัวใจสำคัญคือการใช้กฎนั้นอย่างสม่ำเสมอ เพราะนั่นคือสิ่งที่ทำให้ JSON ของคุณนิ่งและคาดเดาได้ในระยะยาว
ตัวอย่างการใช้งานจริง
ทำให้ API response นิ่งสำหรับ snapshot test
Snapshot test คือเหยื่อรายแรกของ key ที่ไม่มีลำดับ ชุด test อาจผ่านบนเครื่องของเราแต่พังใน CI เพราะสองสภาพแวดล้อม serialize ข้อมูลไม่เหมือนกัน ลองส่ง response ผ่าน key sorter ก่อนถึงมือตัวเขียน snapshot แล้ว snapshot จะเปลี่ยนแปลงเฉพาะเมื่อข้อมูลเปลี่ยนจริงเท่านั้น สีแดงใน CI ก็จะกลับมามีความหมายอีกครั้ง
เปรียบเทียบไฟล์ config
เมื่อ config สองชุด ไฟล์ feature flag หรือไฟล์ Terraform variable เริ่มแยกจากกัน การเรียงทั้งสองฝั่งก่อนจะเปลี่ยน diff ที่รกให้กลายเป็นรายการการเปลี่ยนแปลงจริงที่สะอาดตา ซึ่งทำให้ code review และการตรวจจับ config drift ระหว่างสภาพแวดล้อม dev, staging และ production เร็วขึ้นอย่างเห็นได้ชัด
ทำ canonical JSON ก่อน hashing
ถ้าคุณ hash JSON เพื่อทำ cache key ตรวจสอบความถูกต้องของข้อมูล หรือทำการเซ็นข้อมูล ควรทำให้ข้อความเป็นมาตรฐานเดียวกันก่อนเสมอ เมื่อ key ถูกเรียงเรียบร้อยแล้ว ข้อมูลเชิงตรรกะชุดเดียวกันจะให้ hash เท่ากันทุกครั้ง ไม่ว่า service หรือ library ใดจะเป็นคน serialize มันออกมา
เก็บกวาด JSON ที่แก้ด้วยมือ
ไฟล์ที่ถูกแก้ด้วยมือมักสะสมความรกเอาไว้: key ถูกเพิ่มตามลำดับที่ใครบางคนต้องใช้ในตอนนั้น indentation ไม่สม่ำเสมอ และมีเศษซากจากการ copy-paste การส่งผ่าน sorter เพียงสักรอบจะคืน layout ที่คาดเดาได้กลับมาโดยไม่แตะต้องค่าใด ๆ เลยแม้แต่ตัวเดียว
แนวปฏิบัติที่ดี
- เรียงก่อน diff ไม่ใช่ก่อนเสิร์ฟ. การเรียงเป็นขั้นตอนเพื่อการเปรียบเทียบและการแสดงผล การจ่ายต้นทุนนี้กับทุก request ใน hot path มักไม่คุ้มค่า
- Validate JSON ก่อนเรียง. Parse อินพุตก่อนเสมอ เพื่อให้ error เชิงโครงสร้างแสดงออกมาเป็นข้อความที่ชัดเจน ไม่ใช่ผลลัพธ์ที่แปลกประหลาด
- ระวัง key ซ้ำ. JSON อนุญาตให้มี key ซ้ำในทางเทคนิค แต่ parser ส่วนใหญ่เก็บตัวสุดท้ายไว้เงียบ ๆ การเรียง key ไม่ได้ช่วยแก้ความกำกวมนี้ จึงควรเก็บกวาดให้เรียบร้อยก่อน
- คงลำดับ array ตามเจตนา. ลำดับสมาชิกใน array เป็นข้อมูลที่มีความหมาย มีเพียง key ของ object เท่านั้นที่จัดเรียงใหม่ได้อย่างปลอดภัย
- จับคู่กับการตั้งค่าของ serializer. ปรับ indentation และ case sensitivity ให้ตรงกับ JSON library ของภาษาที่คุณใช้ เพื่อให้ผลลัพธ์จากเครื่องมือและตอน runtime ตรงกัน
- ทำเป็นธรรมเนียมของทีม. บันทึกกฎที่เลือกไว้ให้ชัดเจน เช่น เรียงตามตัวอักษร แบบ case-sensitive และใช้ 2 ช่องว่าง ลงใน style guide เพื่อให้ canonical JSON ของทุกคนในทีมตรงกัน
พร้อมจัดระเบียบ JSON ของคุณหรือยัง เปิด JSON Key Sorter วาง payload ลงไป แล้วดูเอกสารที่รก ๆ สลับกลายเป็น layout ที่นิ่งและเป็นมิตรกับ diff ได้ในคลิกเดียว ใช้ฟรี ทำงานในเบราว์เซอร์ทั้งหมด และใช้เวลาเพียงประมาณสิบวินาทีเท่านั้น
เครื่องมืออื่น ๆ ที่คุณอาจสนใจ:
- JSON Formatter — จัดรูป ตรวจสอบ และย่อ JSON พร้อมปรับ indentation ได้ตามต้องการ
- JSON to YAML Converter — แปลงเอกสาร JSON เป็น YAML ที่สะอาดและอ่านง่าย
- JSON to TypeScript — สร้าง TypeScript interface จาก payload JSON ได้โดยตรง
ขอให้สนุกกับการเรียง key!
คำถามที่พบบ่อย
ถ: การเรียง key ใน JSON ทำให้ข้อมูลเปลี่ยนความหมายหรือไม่? ตอบ: ไม่เปลี่ยน ลำดับของ key ภายใน object ไม่ใช่ส่วนหนึ่งของข้อมูลตามข้อกำหนด JSON เอกสารที่เรียงแล้วกับต้นฉบับจึงเหมือนกันในเชิงความหมาย โดยค่า โครงสร้าง และลำดับสมาชิกใน array ถูกเก็บไว้ครบถ้วนทุกจุด
ถ: เครื่องมือนี้เรียง array ด้วยหรือไม่? ตอบ: ไม่เรียง และนั่นเป็นเจตนา array เป็น collection ที่มีลำดับใน JSON การสลับสมาชิกจึงถือเป็นการเปลี่ยนข้อมูล เครื่องมือจัดลำดับเฉพาะ key ของ object รวมถึงชั้นที่ซ้อนอยู่ด้านใน ส่วนลำดับสมาชิกใน array จะไม่ถูกแตะต้องเลย
ถ: ทำไมผลลัพธ์ของฉันต่างจาก JSON key sorter ตัวอื่น? ตอบ: โหมดการเรียง case sensitivity ทิศทาง และ indentation ล้วนมีผลต่อผลลัพธ์ เครื่องมือสองตัวที่ตั้งค่าไม่เหมือนกันจะให้ข้อความต่างกันจากอินพุตชุดเดียวกัน เมื่อต้องเปรียบเทียบผลลัพธ์จึงควรใช้ตัวเลือกชุดเดียวกันทั้งสองฝั่ง
ถ: วาง JSON ที่มีข้อมูลละเอียดอ่อนได้ปลอดภัยหรือไม่? ตอบ: ปลอดภัย เครื่องมือทำงานทั้งหมดในเบราว์เซอร์ของคุณ ข้อความที่วางจะถูกประมวลผลในเครื่องเท่านั้นและไม่มีการอัปโหลดไปยังเซิร์ฟเวอร์ใด ๆ