AutoValue 및 다형성을 사용하는 Gson
12391 단어 polymorphismandroidapijson
이전 솔루션은 제공된 모든 필드를 포함하는 HashMap을 갖는 것이었습니다. 그런 다음 애플리케이션은 반환된 객체의 종류를 확인하고 필요한 모든 키-값 쌍이 사용 가능한 데이터로 채워졌는지 결정해야 했습니다. 이것은 선호되는 솔루션이 아니며 오류가 발생하기 쉽습니다.
사용자 지정 (역)직렬 변환기를 살펴보기 위해 많은 제안이 이루어졌는데, 이는 좋은 생각이지만 많은 작업이 필요합니다. 나는 Gson 저장소에서 "hidden"RuntimeTypeAdapterFactory 클래스를 발견하여 대부분의 문제를 아주 훌륭하게 해결했습니다.
예제 문제
예를 들어 다음 JSON 구조를 사용하십시오.
{
"article": {
"title": "Hello world",
"body": [{
"type": "text",
"text": "Hi there"
}, {
"type": "image",
"source": "https://example.com/hello-world-banner.jpg",
"author": "John Doe",
"description": "Hello World! banner"
}, {
"type": "video",
"source": "http://mirrorblender.top-ix.org/peach/bigbuckbunny_movies/big_buck_bunny_1080p_surround.avi",
"thumbnail": "https://peach.blender.org/wp-content/uploads/dl_1080p.jpg",
"title": "Big Buck Bunny",
"duration": 574
}
]
}
}
보시다시피
body
배열의 개체에는 반환되는 개체의 유형을 결정하는 type
필드가 있습니다. 이렇게 하면 개체를 고유한 존경하는 모델로 구문 분석할 수 있는 유연성을 얻을 수 있습니다. 이 경우에는 "text
", "image
"및 "video
"여야 합니다. Google의 AutoValue를 사용하여 아래의 3가지 모델 예를 참조하십시오.public interface Block {
}
@AutoValue
public abstract class TextBlock implements Block {
@SerializedName("text")
public abstract String text();
}
@AutoValue
public abstract class ImageBlock implements Block {
@SerializedName("source")
public abstract String source();
@Nullable
@SerializedName("author")
public abstract String author();
@Nullable
@SerializedName("description")
public abstract String description();
}
@AutoValue
public abstract class VideoBlock implements Block {
@SerializedName("source")
public abstract String source();
@SerializedName("thumbnail")
public abstract String thumbnail();
@SerializedName("title")
public abstract String title();
@SerializedName("duration")
public abstract int duration();
}
(간결함을 위해 위의 예에서 빌더 및 Gson 유형 어댑터 생성기를 생략했습니다.)
해결책
먼저 Article 모델 자체를 만들어야 합니다. 아래 예에서
List<Block>
반환 유형을 확인할 수 있습니다. Blocks 예제 코드를 살펴보면 모두 Block 인터페이스를 구현하는 것을 볼 수 있습니다. 이렇게 하면 향후 업데이트에서 지원하고자 하는 새로운 유형의 객체를 쉽게 정의할 수 있습니다.@AutoValue
public abstract class Article {
@SerializedName("title")
public abstract String title();
@SerializedName("blocks")
public abstract List<Block> blocks();
}
그러나 지금 그것을 구문 분석합니다. 여기에 RuntimeTypeAdapterFactory라는 마법이 개입합니다! Gson 파서를 생성할 때 모든 종류의 어댑터 팩토리를 등록할 수 있습니다. 생성된 AutoValue 어댑터와 런타임 어댑터를 추가하면 설정이 완료됩니다.
예를 들어:
RuntimeTypeAdapterFactory<Block> articleBlockFactory = RuntimeTypeAdapterFactory.of(Block.class, "type")
.registerSubtype(TextBlock.class, "text")
.registerSubtype(ImageBlock.class, "image")
.registerSubtype(VideoBlock.class, "video");
Gson gson = new GsonBuilder()
.setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
.registerTypeAdapterFactory(AutoValueTypeAdapterFactory.create())
.registerTypeAdapterFactory(articleBlockFactory)
.create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.example.com/")
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
Gson 구문 분석기가 유형
Block
의 개체를 만날 때마다 어댑터는 정의된 하위 유형으로 구문 분석할 수 있는지 확인합니다. API가 "type"
와 다른 필드에 유형을 정의하는 경우 이를 제공할 수 있습니다. "type"
는 키의 기본 이름이므로 API가 이 방식으로 작동하는 경우 완전히 생략할 수 있습니다.주의 사항
나는 내 목적을 위해 해결해야 할 몇 가지 사소한 문제에 부딪쳤다. 이러한 결과는 RuntimeTypeAdapterFactory 작업을 시작할 때를 알 때 유용할 수도 있습니다.
null
"type"
필드는 모델에 반환되지 않습니다. — 이 정보를 원하면 다시 추가해야 합니다즐거운 코딩!
Reference
이 문제에 관하여(AutoValue 및 다형성을 사용하는 Gson), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/hameteman/gson-using-autovalue-and-polymorphism-2470텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)