การทำให้เป็นอนุกรม Enum ที่ใช้อินเทอร์เฟซกับ Gson

ฉันมีรหัสห้องสมุดบางส่วนที่ฉันต้องทำให้เป็นอนุกรม ฟิลด์หนึ่งถูกกำหนดให้เป็นอินเทอร์เฟซ Foo ซึ่งเป็นเพียงอินเทอร์เฟซของมาร์กเกอร์ รหัสไคลเอ็นต์ควรสร้าง Enum ที่ใช้ Foo เพื่อให้สามารถขยายรายการประเภทย่อยได้ตามต้องการ

ฉันไม่สามารถทำให้สิ่งนี้เป็นอนุกรมใน Gson ด้วยอะแดปเตอร์ประเภทได้ ข้อยกเว้นที่ฉันได้รับคือ:

java.lang.IllegalStateException: ไม่ใช่วัตถุ JSON: "SETUP"

โดยที่การตั้งค่าเป็นองค์ประกอบหนึ่งของการระบุไคลเอ็นต์ Bar

ฉันได้เพิ่ม TypeAdapter ที่กำหนด Foo เป็น supertype และ Bar เป็นประเภทย่อย โดยใช้รหัส Gson RuntimeTypeAdapter (ตัวช่วย Gson จาก Google) มีความคิดเห็นเกี่ยวกับสิ่งที่ฉันทำผิดหรือ Gson ไม่รองรับโครงสร้างประเภทนี้

ฉันเชื่อว่าฉันสามารถแก้ไขได้โดยทำให้ Foo เป็นคลาสนามธรรมและ Setup เป็นคลาสย่อย แต่นั่นก็ไม่ค่อยดีนักเนื่องจาก enum เป็นเพียงโทเค็นจริงๆ


person L. Blanc    schedule 28.03.2017    source แหล่งที่มา
comment
คงจะดีไม่น้อยหากคุณโพสต์ข้อยกเว้น stacktrace อย่างน้อยก็เพื่อสาเหตุที่แท้จริง MCVE และเวอร์ชันของ Gson ที่คุณใช้อยู่   -  person Lyubomyr Shaydariv    schedule 28.03.2017


คำตอบ (1)


ฉันคิดว่าปัญหาเกี่ยวข้องกับความจริงที่ว่าเนื่องจากคุณกำลังใช้งานอินเทอร์เฟซ Gson จึงคาดหวังคลาส แต่ได้รับ enum แทน นี่อาจเป็นข้อผิดพลาด ฉันจะต้องมองให้ลึกกว่านี้

ไม่ว่าในกรณีใด ฉันคิดว่าวิธีแก้ปัญหาที่ดีที่สุดสำหรับปัญหาของคุณคือการใช้ซีเรียลไลเซอร์/ดีซีเรียลไลเซอร์แบบกำหนดเองสำหรับคำอธิบายประกอบ อินเทอร์เฟซของคุณจะต้องมีคลาสย่อยเพื่อใช้เมธอด name() (ซึ่งคุณควรนำไปใช้แล้วเนื่องจากเป็น enum) จากนั้นจึงเรียกคลาสนั้นเพื่อทำซีเรียลไลซ์เซชัน

นี่คือตัวอย่าง:

public class MyInterfaceSerializer implements JsonSerializer<MyInterface> {

public JsonElement serialize(MyInterface src, Type typeOfSrc,
        JsonSerializationContext context) {

    return context.serialize(src.name());
}

โดยพื้นฐานแล้วการดีซีเรียลไลเซชันจะเหมือนกัน แต่ดีซีเรียลไลเซอร์ (อาจเป็นและควรเป็นคลาสเดียวกัน) จะใช้ JsonDeserializer และสร้างตัวอย่าง enum ของคุณ

person Aurasphere    schedule 28.03.2017
comment
คุณจัดการเพื่อสร้างข้อผิดพลาดที่ OP ได้รับซ้ำหรือไม่ ฉันไม่สามารถทำซ้ำได้สำหรับการแมปคลาสหรือค่าแจงนับเดียว - person Lyubomyr Shaydariv; 28.03.2017
comment
Gson คาดหวังวัตถุ แต่ได้รับ enum แทนที่จะเป็น enum ที่เป็น Object - person Sean Patrick Floyd; 28.03.2017
comment
@LyubomyrShaydariv ฉันทำไม่ได้ แต่ฉันไม่รู้ว่าเขาใช้ Gson รุ่นใด - person Aurasphere; 28.03.2017
comment
@Aurasphere LOL enum ก็เป็นคลาสเช่นกัน :-) ณ รันไทม์ แทบจะไม่มีอะไรที่จะแยกความแตกต่าง enum จากอ็อบเจ็กต์อื่นแบบเก่าได้ มันเป็นเพียงน้ำตาลคอมไพเลอร์ - person Sean Patrick Floyd; 28.03.2017
comment
@SeanPatrickFloyd คุณสามารถดูได้ว่าคลาสนั้นเป็น anum ที่รันไทม์หรือไม่หากคุณใช้ instanceof และฉันสงสัยว่านั่นคือปัญหา OP อย่างแน่นอน - person Aurasphere; 28.03.2017
comment
@Aurasphere ฉันรู้และฉันเห็นด้วยกับข้อสรุปของคุณ ไม่ใช่กับถ้อยคำ - person Sean Patrick Floyd; 28.03.2017
comment
@SeanPatrickFloyd ฉันขอโทษ ฉันไม่เก่งเรื่องถ้อยคำ... นี่คือเหตุผลว่าทำไมฉันถึงเป็นโปรแกรมเมอร์ไม่ใช่กวี :P ahaha - person Aurasphere; 28.03.2017
comment
อย่างไรก็ตาม บรรทัดสุดท้ายจะไม่คอมไพล์ เว้นแต่อินเทอร์เฟซจะมีเมธอด name() แต่คุณสามารถแทนที่ด้วย return context.serialize(Enum.class.cast(src).name()); - person Sean Patrick Floyd; 28.03.2017
comment
อินเทอร์เฟซของคุณจะต้องมีคลาสย่อยเพื่อใช้เมธอด name() (ซึ่งคุณควรนำไปใช้แล้วเนื่องจากเป็น enum) จากนั้นจึงเรียกคลาสนั้นเพื่อทำซีเรียลไลซ์เซชัน ใช่นั่นคือสิ่งที่ฉันหมายถึงที่นี่ - person Aurasphere; 28.03.2017
comment
อ่า ขอโทษที พลาดไป - person Sean Patrick Floyd; 28.03.2017
comment
ไม่มีปัญหา อาจมีข้อผิดพลาดอื่นๆ อีก เนื่องจากฉันเขียนมันทันทีและไม่สามารถทดสอบบนคอมพิวเตอร์เครื่องนี้ได้ ดังนั้นจึงเป็นเรื่องดีที่จะมีการตรวจทาน! ขอบคุณ! - person Aurasphere; 28.03.2017