Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Java

วิธีแก้ไข Expected BEGIN_OBJECT but was BEGIN_ARRAY ใน Gson (Java)

ขณะ 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