นี่เป็นคำถามที่ดีเพราะแยกบางสิ่งที่ควรจะง่าย แต่ต้องใช้โค้ดจำนวนมาก
ในการเริ่มต้นให้เขียนบทคัดย่อTypeAdapterFactory
ที่ช่วยให้คุณสามารถแก้ไขข้อมูลที่ส่งออกได้ ตัวอย่างนี้ใช้ API ใหม่ใน Gson 2.2 ที่เรียกgetDelegateAdapter()
ว่าช่วยให้คุณค้นหาอะแดปเตอร์ที่ Gson จะใช้ตามค่าเริ่มต้น อะแด็ปเตอร์ที่ได้รับมอบหมายมีประโยชน์อย่างยิ่งหากคุณต้องการปรับเปลี่ยนลักษณะการทำงานมาตรฐาน และแตกต่างจากอะแดปเตอร์ประเภทกำหนดเองเต็มรูปแบบคือจะอัปเดตโดยอัตโนมัติเมื่อคุณเพิ่มและลบฟิลด์
public abstract class CustomizedTypeAdapterFactory<C>
implements TypeAdapterFactory {
private final Class<C> customizedClass;
public CustomizedTypeAdapterFactory(Class<C> customizedClass) {
this.customizedClass = customizedClass;
}
@SuppressWarnings("unchecked")
public final <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
return type.getRawType() == customizedClass
? (TypeAdapter<T>) customizeMyClassAdapter(gson, (TypeToken<C>) type)
: null;
}
private TypeAdapter<C> customizeMyClassAdapter(Gson gson, TypeToken<C> type) {
final TypeAdapter<C> delegate = gson.getDelegateAdapter(this, type);
final TypeAdapter<JsonElement> elementAdapter = gson.getAdapter(JsonElement.class);
return new TypeAdapter<C>() {
@Override public void write(JsonWriter out, C value) throws IOException {
JsonElement tree = delegate.toJsonTree(value);
beforeWrite(value, tree);
elementAdapter.write(out, tree);
}
@Override public C read(JsonReader in) throws IOException {
JsonElement tree = elementAdapter.read(in);
afterRead(tree);
return delegate.fromJsonTree(tree);
}
};
}
protected void beforeWrite(C source, JsonElement toSerialize) {
}
protected void afterRead(JsonElement deserialized) {
}
}
คลาสข้างต้นใช้การทำให้เป็นอนุกรมเริ่มต้นเพื่อรับทรี JSON (แสดงโดยJsonElement
) จากนั้นเรียกใช้เมธอด hook beforeWrite()
เพื่อให้คลาสย่อยปรับแต่งทรีนั้น ในทำนองเดียวกันสำหรับ deserialization กับafterRead()
.
ต่อไปเราจะย่อยคลาสนี้สำหรับMyClass
ตัวอย่างเฉพาะ เพื่อเป็นตัวอย่างฉันจะเพิ่มคุณสมบัติสังเคราะห์ที่เรียกว่า 'size' ลงในแผนที่เมื่อมันต่อเนื่องกัน และสำหรับความสมมาตรฉันจะลบออกเมื่อมันถูก deserialized ในทางปฏิบัตินี่อาจเป็นการปรับแต่งใด ๆ
private class MyClassTypeAdapterFactory extends CustomizedTypeAdapterFactory<MyClass> {
private MyClassTypeAdapterFactory() {
super(MyClass.class);
}
@Override protected void beforeWrite(MyClass source, JsonElement toSerialize) {
JsonObject custom = toSerialize.getAsJsonObject().get("custom").getAsJsonObject();
custom.add("size", new JsonPrimitive(custom.entrySet().size()));
}
@Override protected void afterRead(JsonElement deserialized) {
JsonObject custom = deserialized.getAsJsonObject().get("custom").getAsJsonObject();
custom.remove("size");
}
}
ในที่สุดก็รวมเข้าด้วยกันโดยการสร้างGson
อินสแตนซ์ที่กำหนดเองที่ใช้อะแดปเตอร์ชนิดใหม่:
Gson gson = new GsonBuilder()
.registerTypeAdapterFactory(new MyClassTypeAdapterFactory())
.create();
ใหม่ Gson ของTypeAdapterและTypeAdapterFactoryประเภทที่มีประสิทธิภาพมาก แต่พวกเขายังนามธรรมและใช้การปฏิบัติที่จะใช้อย่างมีประสิทธิภาพ หวังว่าตัวอย่างนี้จะเป็นประโยชน์!