GSON @SerializedName หลายรายการต่อฟิลด์หรือไม่


104

มีวิธีใดใน Gson ในการแมปฟิลด์ JSON หลายฟิลด์กับตัวแปรสมาชิกอ็อบเจ็กต์ Java เดียวหรือไม่?

สมมติว่าฉันมีคลาส Java ...

public class MyClass {
    String id;
    String name;
}

ฉันต้องการใช้คลาสเดี่ยวนี้กับสองบริการที่แตกต่างกัน อย่างไรก็ตามบริการทั้งสองนี้แตกต่างกันในวิธีการส่งคืนข้อมูล ...

{ "id": 2341, "person": "Bob" }

... และ ...

{ "id": 5382, "user": "Mary" }

... ตามลำดับ.

มีวิธีใดในการแมปทั้งฟิลด์"person"และ"user"ฟิลด์ในสตริง JSON กับnameฟิลด์ในออบเจ็กต์ Java หรือไม่

(หมายเหตุ: ฉันแค่ต้องแปลงจากสตริง JSON เป็นออบเจ็กต์ Java เท่านั้น - ไม่เคยเป็นอย่างอื่นเลย)


1
นี่คือคำอธิบายที่ง่ายและสมบูรณ์แบบ futurestud.io/tutorials/…
Atul Bhardwaj

คำตอบ:


239

ในเดือนตุลาคม 2015 Gson เวอร์ชัน 2.4 (การเปลี่ยนแปลง ) ได้เพิ่มความสามารถในการใช้ชื่ออื่น / หลายชื่อ@SerializedNameเมื่อต้องการแยกส่วน ไม่จำเป็นต้องใช้ TypeAdapter แบบกำหนดเองอีกต่อไป!

การใช้งาน:

@SerializedName(value="name", alternate={"person", "user"})

https://www.javadoc.io/doc/com.google.code.gson/gson/2.6.2/com/google/gson/annotations/SerializedName.html


1
นี่คือคำอธิบายที่ง่ายและสมบูรณ์แบบ futurestud.io/tutorials/…
Atul Bhardwaj

สุดทึ่ง! ขอบคุณสำหรับคำตอบนี้!
sunlover3

คำตอบที่ดีขอบคุณ!
ฎ. รูด

27

ไม่สนับสนุนการกำหนด@SerializedNameคำอธิบายประกอบหลายรายการให้กับฟิลด์ที่ Gson

เหตุผล: โดยค่าเริ่มต้น Deserialization ได้รับการจัดการด้วย LinkedHashMap และคีย์ถูกกำหนดโดยชื่อฟิลด์ของ json ขาเข้า (ไม่ใช่ชื่อฟิลด์ของคลาสที่กำหนดเองหรือ serializedNames) และมีการแม็พแบบหนึ่งต่อหนึ่ง คุณสามารถดูการดำเนินงาน (วิธี deserialization ทำงาน) ในReflectiveTypeAdapterFactoryระดับชั้นของชั้นAdapter<T>'s read(JsonReader in)วิธี

การแก้ไข: คุณสามารถเขียนเองTypeAdapterซึ่งจับname, personและuserแท็ก JSON และแผนที่พวกเขาไปยังเขตข้อมูลชื่อของชั้นเองของคุณMyClass:

class MyClassTypeAdapter extends TypeAdapter<MyClass> {

    @Override
    public MyClass read(final JsonReader in) throws IOException {
        final MyClass myClassInstance = new MyClass();

        in.beginObject();
        while (in.hasNext()) {
            String jsonTag = in.nextName();
            if ("id".equals(jsonTag)) {
                myClassInstance.id = in.nextInt();
            } else if ("name".equals(jsonTag) 
                    || "person".equals(jsonTag)
                    || "user".equals(jsonTag)) {
                myClassInstance.name = in.nextString();
            }
        }
        in.endObject();

        return myClassInstance;
    }

    @Override
    public void write(final JsonWriter out, final MyClass myClassInstance)
            throws IOException {
        out.beginObject();
        out.name("id").value(myClassInstance.id);
        out.name("name").value(myClassInstance.name);
        out.endObject();
    }
}

กรณีทดสอบ:

    String jsonVal0 = "{\"id\": 5382, \"user\": \"Mary\" }";
    String jsonVal1 = "{\"id\": 2341, \"person\": \"Bob\"}";

    final GsonBuilder gsonBuilder = new GsonBuilder();
    gsonBuilder.registerTypeAdapter(MyClass.class, new MyClassTypeAdapter());
    final Gson gson = gsonBuilder.create();

    MyClass myClassInstance0 = gson.fromJson(jsonVal0, MyClass.class);
    MyClass myClassInstance1 = gson.fromJson(jsonVal1, MyClass.class);

    System.out.println("jsonVal0 :" + gson.toJson(myClassInstance0));
    // output: jsonVal0 :{"id":5382,"name":"Mary"}

    System.out.println("jsonVal1 :" + gson.toJson(myClassInstance1));
    // output: jsonVal1 :{"id":2341,"name":"Bob"}

ตัวอย่างเกี่ยวกับ TypeAdapters

แก้ไข 2016.04.06:ตามที่ @Mathieu Castets เขียนไว้ในคำตอบของเขาตอนนี้รองรับแล้ว (นั่นคือคำตอบที่ถูกต้องสำหรับคำถามนี้)

สตริงนามธรรมสาธารณะ []
ผลตอบแทนทางเลือก : ชื่อทางเลือกของฟิลด์เมื่อมีการ deserialized
ค่าเริ่มต้น: {}


นี่คือคำอธิบายที่ง่ายและสมบูรณ์แบบ futurestud.io/tutorials/…
Atul Bhardwaj


8

สำหรับ KOTLIN ฉันใช้ด้านล่าง แต่ไม่ได้ผล

@SerializedName(value="name", alternate= ["person", "user"])

ฉันจึงแก้ไขมันและมันก็ใช้ได้ดี !!

@SerializedName(value="name", alternate= arrayOf("person", "user"))
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.