이것은 쉽지만 실제로 많은 코드가 필요한 것을 분리하기 때문에 좋은 질문입니다.
시작하려면 TypeAdapterFactory
나가는 데이터를 수정할 수있는 후크를 제공 하는 초록 을 작성하십시오 . 이 예에서는 getDelegateAdapter()
Gson이 기본적으로 사용할 어댑터를 조회 할 수 있도록하는 Gson 2.2의 새 API를 사용합니다. 델리게이트 어댑터는 표준 동작을 조정하려는 경우 매우 편리합니다. 또한 전체 사용자 지정 유형 어댑터와 달리 필드를 추가 및 제거 할 때 자동으로 최신 상태로 유지됩니다.
public abstract class CustomizedTypeAdapterFactory<C>
implements TypeAdapterFactory {
private final Class<C> customizedClass;
public CustomizedTypeAdapterFactory(Class<C> customizedClass) {
this.customizedClass = customizedClass;
}
@SuppressWarnings("unchecked") // we use a runtime check to guarantee that 'C' and 'T' are equal
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);
}
};
}
/**
* Override this to muck with {@code toSerialize} before it is written to
* the outgoing JSON stream.
*/
protected void beforeWrite(C source, JsonElement toSerialize) {
}
/**
* Override this to muck with {@code deserialized} before it parsed into
* the application type.
*/
protected void afterRead(JsonElement deserialized) {
}
}
위의 클래스는 기본 직렬화를 사용하여 JSON 트리 (로 JsonElement
표시됨)를 가져온 다음 후크 메서드 beforeWrite()
를 호출 하여 하위 클래스가 해당 트리를 사용자 지정할 수 있도록합니다. .NET을 사용한 역 직렬화와 유사합니다 afterRead()
.
다음으로 특정 MyClass
예제를 위해 이것을 하위 클래스로 만듭니다. 설명을 위해 맵이 직렬화 될 때 'size'라는 합성 속성을 맵에 추가합니다. 대칭을 위해 역 직렬화 될 때 제거합니다. 실제로 이것은 모든 사용자 정의가 될 수 있습니다.
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 유형은 매우 강력하지만 추상적이고 효과적으로 사용하기 위해 연습을합니다. 이 예제가 유용하기를 바랍니다.