Response
클래스에 응답 객체가지도로 변환되면 무시 될 특수 Gson 주석이있을 수 있으므로지도를 사용하는 것이 최선의 방법이 아닙니다.
는 다음과 같은 간단한 응답 클래스를 가정 :
이
final class Response<T> {
@Expose(serialize = true)
final String status = "STATUS";
@Expose(serialize = true)
final String message = "MESSAGE";
@Expose(serialize = true)
final T data;
@Expose(serialize = false, deserialize = false)
final String whatever = "WHATEVER";
Response(final T data) {
this.data = data;
}
}
이 응답 단순 또 다른 GSON 주석을 사용하지 않습니다. 동적 필드 이름 변경의 임시 사용 : 주요 트릭은 여기에 중간 JSON 트리를 만들고 동적 속성 이름을 대체되는 것을
final Gson gson = new GsonBuilder()
.excludeFieldsWithoutExposeAnnotation()
// ... any Gson configuration here ...
.create();
final Response<List<String>> response = new Response<>(ImmutableList.of("foo", "bar"));
final JsonElement jsonTree = gson.toJsonTree(response, stringListResponseTypeToken.getType());
final JsonObject responseJson = jsonTree.getAsJsonObject();
final JsonElement dataPropertyJson = responseJson.get("data");
responseJson.remove("data");
responseJson.add(response.getClass().getSimpleName(), dataPropertyJson);
gson.toJson(responseJson, System.out);
참고. 불행히도이 솔루션에는 중간 JSON 트리가 필요합니다. 또 다른 "Gson-ish"솔루션은 필요할 때마다 응답 개체를 다시 매핑하지 않기 위해 특수 유형 어댑터를 만듭니다. 유형 어댑터 공장과 유형 어댑터로 구현됩니다
final Gson gson = new GsonBuilder()
.excludeFieldsWithoutExposeAnnotation()
// ... any Gson configuration here ...
.registerTypeAdapterFactory(getDynamicPropertyResponseTypeAdapterFactory())
.create();
final Response<List<String>> response = new Response<>(ImmutableList.of("foo", "bar"));
gson.toJson(response, stringListResponseTypeToken.getType(), System.out);
은 다음과 같습니다
이러한 유형의 어댑터 공장은 처리 클래스
Response
경우 무한 재귀을 피하기 위해 다운 스트림 타입의 어댑터를 선택합니다하는 것으로
final class DynamicPropertyResponseTypeAdapterFactory
implements TypeAdapterFactory {
private static final TypeAdapterFactory dynamicPropertyResponseTypeAdapterFactory = new DynamicPropertyResponseTypeAdapterFactory();
private DynamicPropertyResponseTypeAdapterFactory() {
}
static TypeAdapterFactory getDynamicPropertyResponseTypeAdapterFactory() {
return dynamicPropertyResponseTypeAdapterFactory;
}
@Override
public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> typeToken) {
if (Response.class.isAssignableFrom(typeToken.getRawType())) {
@SuppressWarnings("unchecked")
final TypeAdapter<Response<Object>> delegateTypeAdapter = (TypeAdapter<Response<Object>>) gson.getDelegateAdapter(this, typeToken);
@SuppressWarnings("unchecked")
final TypeAdapter<T> castTypeAdapter = (TypeAdapter<T>) getDynamicPropertyResponseJsonTypeAdapter(delegateTypeAdapter, gson);
return castTypeAdapter;
}
return null;
}
}
하고, 그렇지 않으면 null
이 반환되어 Gson이 자체 (비) 직렬화 전략을 사용하게합니다.
final class DynamicPropertyResponseJsonTypeAdapter<T>
extends TypeAdapter<Response<T>> {
private final TypeAdapter<Response<T>> delegateTypeAdapter;
private final Gson gson;
private DynamicPropertyResponseJsonTypeAdapter(final TypeAdapter<Response<T>> delegateTypeAdapter, final Gson gson) {
this.delegateTypeAdapter = delegateTypeAdapter;
this.gson = gson;
}
static <T> TypeAdapter<Response<T>> getDynamicPropertyResponseJsonTypeAdapter(final TypeAdapter<Response<T>> delegateTypeAdapter, final Gson gson) {
return new DynamicPropertyResponseJsonTypeAdapter<>(delegateTypeAdapter, gson);
}
@Override
@SuppressWarnings("resource")
public void write(final JsonWriter out, final Response<T> response)
throws IOException {
if (response == null) {
out.nullValue();
return;
}
final JsonElement jsonTree = delegateTypeAdapter.toJsonTree(response);
final JsonObject responseJson = jsonTree.getAsJsonObject();
final JsonElement dataPropertyJson = responseJson.get("data");
responseJson.remove("data");
responseJson.add(response.getClass().getSimpleName(), dataPropertyJson);
gson.toJson(responseJson, out);
}
@Override
public Response<T> read(final JsonReader in) {
throw new UnsupportedOperationException();
}
}
동일하지 아주 싼 트릭 위에서 사용되지만 지금은 Gson
인스턴스의 일부로서 작동합니다.다음과 같이 두 가지 경우의 출력은 :
{ "상태": "STATUS", "메시지": "메시지", "응답"[ "foo에", "바"]}
당신이 고려해야 할 수 있습니다
또 다른 옵션은 다음과 같습니다
- 는
Response
클래스 추상적 만들기와 이름이 하드 코딩 있어야하는 경우 하위 클래스가 @SerializedName
를 통해 자신의 data
필드 이름을 정의하는 데시키는.
- 구현 코드
ReflectiveTypeAdapterFactory
(Gson 소스 코드 참조)을 만들고 JSON 트리를 생성하지 않고 필드 이름을 동적으로 만듭니다.