Java อ่านข้อมูล JSON โดยไม่ใช้ library

java8_logo

ข้อมูลแบบเจสัน (JSON: Javascript Object Notation) เป็นที่นิยมในกลุ่มผู้พัฒนาเว็บไซต์ เพราะเป็นรูปแบบข้อมูลที่ใช้เป็นพื้นฐานในจาวาสคริปต์ (Javascript)

ถ้าต้องการนำข้อมูลเจสันมาใช้งานในจาวา ก็มีไลบรารี (library) ให้เลือกใช้มากมาย เช่น org.json, gson, jsonp และ jackson เป็นต้น

แต่จริงๆแล้วใน JDK ก็รองรับการประมวลภาษาในตระกูลจาวาสคริปต์อยู่แล้ว นั่นคือ ScriptEngine โดยประมวลผลและแลกเปลี่ยนข้อมูลไปมาระหว่างจาวาและจาวาสคริปต์ จึงสงสัยว่า ถ้าอย่างนั้น จะใช้ ScriptEngine ในการอ่านข้อมูลเจสันจากภายนอกได้หรือไม่ โดยไม่ต้องใช้ไลบรารีใดๆเลย

วิธีการอ่านข้อมูลเจสันด้วย ScriptEngine:

  1. อ่านข้อมูลเจสันนั้นๆในรูปแบบสตริง (String) อาจจะดึงข้อมูลผ่าน http ก็ได้
  2. ScriptEngine เป็นคลาสที่ใช้ประมวลผลคำสั่งภาษาสคริปต์ จึงต้องเพิ่มการ assign ค่าเพื่อให้เกิดการประมวลผล ไม่เช่นนั้น ScriptEngine จะเกิดข้อผิดพลาด วิธีการง่ายที่สุดคือ เพิ่มการ assign ค่าเข้าไปที่ด้านหน้า จะได้ o=<ข้อมูลเจสันจากข้อ 1>
  3. เขียนคำสั่งดังนี้

ScriptEngine engine = new ScriptEngineManager().getEngineByName(“ECMAScript”);
Map result = (Map) engine.eval(<ข้อมูลสตริงจากข้อ 2>);

จากนั้นเราสามารถนำตัวแปร result มาใช้งานในรูปแบบแม็พ (Map) ได้ โดยการแคสติ้ง (cast) ข้อมูลเจสันส่วนมากจะเป็นแบบคู่คีย์-แวลู (key-value pair) โดยที่คีย์เป็นสตริง ส่วนแวลูเป็นวัตถุ (Object) ที่สามารถแคสต์ซ้อนเป็นแม็พตามลำดับขั้นไปเรื่อยๆได้ แต่ถ้าข้อมูลเป็นแบบพรีมิทีฟ (primitive) เช่น int จะสามารถแคสต์ตรงๆได้

คำสั่งข้างต้นได้ทดลองใช้งานบน JDK 8 ของออราเคิล (Oracle) แต่เกิดปัญหา ClassCastException: sun.org.mozilla.javascript.internal.NativeObject cannot be cast to java.util.Map เมื่อใช้กับ OpenJDK 7

สาเหตุเกิดจากบั๊กใน OpenJDK 7 ที่ไม่ได้รวมคลาสเหล่านี้เข้ามาในไฟล์ rt.jar ทำให้เกิดปัญหาขณะรัน (runtime) แต่ไม่เกิดปัญหาขณะคอมไพล์ (compile) วิธีแก้ไขที่ง่ายที่สุดคืออัพเกรดไปใช้ OpenJDK 8 ขึ้นไป รายละเอียดสามารถตามไปดูในลิงค์อ้างอิงสุดท้าย

ที่มา:

สแลช (Slash)