ขณะ deserialize Gson คาดหวัง JSON object แต่พบ JSON array เนื่องจากไม่สามารถแปลงจากหนึ่งไปอีกได้ จึงโยน error: "JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY" ในขณะรันไทม์
ตัวอย่างที่ทำให้ Error
import com.google.gson.Gson;
public class GsonErrorTest {
public static void main(String args[]) throws Exception {
String json = "{\"employee\":[{\"name\":\"Raja Ramesh\", \"technology\":\"java\"}]}";
Gson gson = new Gson();
Software software = gson.fromJson(json, Software.class);
System.out.println(software);
}
}
class Software {
Employee employee; // คาดหวัง single object
}
class Employee {
String name;
String technology;
}
ผลลัพธ์ (Error)
Exception in thread "main"
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY
at line 1 column 14
...
Caused by: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY
at line 1 column 14
สาเหตุ
JSON มี "employee": [...] (array) แต่ Java class มี Employee employee (single object) Gson ไม่สามารถ map array ให้ single object ได้
วิธีแก้ไข: เปลี่ยน POJO Type เป็น Collection หรือ Array
import java.util.List;
import com.google.gson.Gson;
public class GsonListTest {
public static void main(String args[]) throws Exception {
String jsonString = "{\"employees\":[{\"name\":\"Raja Ramesh\", \"technology\":\"Java\"}]}";
Gson gson = new Gson();
Software software = gson.fromJson(jsonString, Software.class);
System.out.println(software);
}
}
class Software {
List<Employee> employees; // เปลี่ยนเป็น List
@Override
public String toString() {
return "Software [employees=" + employees + "]";
}
}
class Employee {
String name;
String technology;
@Override
public String toString() {
return "Employee [name=" + name + ", technology=" + technology + "]";
}
}
ผลลัพธ์ (Output)
Software [employees=[Employee [name=Raja Ramesh, technology=Java]]]
วิธีแก้ไขอื่นๆ
- ใช้ Array แทน List:
Employee[] employees; - ใช้ JsonDeserializer custom: implement logic เองในการ deserialize
- แก้ JSON source: เปลี่ยน JSON ให้เป็น object แทน array (ถ้าควบคุม JSON ได้)
- ใช้ @SerializedName: map key ที่ต่างกัน
สรุป
Error "Expected BEGIN_OBJECT but was BEGIN_ARRAY" เกิดจาก type mismatch ระหว่าง JSON (array) และ Java field (object) แก้ไขโดยเปลี่ยน Java field type เป็น Collection หรือ Array ให้ตรงกับ JSON structure