동적 ArrayList 항목 유형이있는 Gson TypeToken
이 코드가 있습니다.
Type typeOfObjectsList = new TypeToken<ArrayList<myClass>>() {}.getType();
List<myClass> objectsList = new Gson().fromJson(json, typeOfObjectsList);
JSON 문자열을 List
객체 로 변환 합니다. 하지만 이제 런타임에 정의 된 ArrayList
동적 유형 (단지 myClass
)을 사용 하고 싶습니다 .
ArrayList
의 항목 유형을 정의 할 것입니다 반사 .
나는 이것을 시도했다 :
private <T> Type setModelAndGetCorrespondingList2(Class<T> type) {
Type typeOfObjectsListNew = new TypeToken<ArrayList<T>>() {}.getType();
return typeOfObjectsListNew;
}
하지만 작동하지 않습니다. 다음은 예외입니다.
java.sql.SQLException: Fail to convert to internal representation: {....my json....}
제안하는 구문이 잘못되었습니다. 다음과 같은
new TypeToken<ArrayList<Class.forName(MyClass)>>
형식 이름이 예상되는 메서드 호출을 전달하려고하기 때문에은 유효하지 않습니다.
다음과 같은
new TypeToken<ArrayList<T>>()
제네릭 (타입 삭제)과 리플렉션이 작동하는 방식 때문에 불가능합니다. 전체 TypeToken
해킹이 작동하는 이유 Class#getGenericSuperclass()
는 다음과 같습니다.
이 Class가 나타내는 엔티티 (클래스, 인터페이스, 기본 유형 또는 void)의 직접 수퍼 클래스를 나타내는 Type을 리턴합니다.
수퍼 클래스가 매개 변수화 된 유형 인 경우 반환 된 Type 객체는 소스 코드에 사용 된 실제 유형 매개 변수를 정확하게 반영해야합니다.
그것을 보는 경우 즉, ArrayList<T>
그는이다 ParameterizedType
그것을 반환하고 당신은 유형 변수가있는 컴파일 시간 값을 추출 할 수 없습니다 T
했을 것입니다.
Type
그리고 ParameterizedType
두 인터페이스이다. 자체 구현의 인스턴스를 제공 할 수 있습니다.
GSON 2.8.0 때문에, 당신은 사용할 수 있습니다 TypeToken#getParameterized(Type rawType, Type... typeArguments)
을 생성 TypeToken
한 후, getType()
트릭을해야한다.
예를 들면 :
TypeToken.getParameterized(ArrayList.class, myClass).getType()
옵션 1-java.lang.reflect.ParameterizedType
직접 구현 하고 Gson에 전달하십시오.
private static class ListParameterizedType implements ParameterizedType {
private Type type;
private ListParameterizedType(Type type) {
this.type = type;
}
@Override
public Type[] getActualTypeArguments() {
return new Type[] {type};
}
@Override
public Type getRawType() {
return ArrayList.class;
}
@Override
public Type getOwnerType() {
return null;
}
// implement equals method too! (as per javadoc)
}
그런 다음 간단히 :
Type type = new ListParameterizedType(clazz);
List<T> list = gson.fromJson(json, type);
당합니다 javadoc는 , 방법도 구현해야 같습니다.
옵션 2- (하지 마십시오) gson 내부 재사용 ...
This will work too, at least with Gson 2.2.4.
Type type = com.google.gson.internal.$Gson$Types.newParameterizedTypeWithOwner(null, ArrayList.class, clazz);
This worked for me:
public <T> List<T> listEntity(Class<T> clazz)
throws WsIntegracaoException {
try {
// Consuming remote method
String strJson = getService().listEntity(clazz.getName());
JsonParser parser = new JsonParser();
JsonArray array = parser.parse(strJson).getAsJsonArray();
List<T> lst = new ArrayList<T>();
for(final JsonElement json: array){
T entity = GSON.fromJson(json, clazz);
lst.add(entity);
}
return lst;
} catch (Exception e) {
throw new WsIntegracaoException(
"WS method error [listEntity()]", e);
}
}
You can do this with Guava's more powerful TypeToken
:
private static <T> Type setModelAndGetCorrespondingList2(Class<T> type) {
return new TypeToken<ArrayList<T>>() {}
.where(new TypeParameter<T>() {}, type)
.getType();
}
sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
workes. No need for custom implementation
Type type = ParameterizedTypeImpl.make(List.class, new Type[]{childrenClazz}, null);
List list = gson.fromJson(json, type);
Can be used with maps and any other collection:
ParameterizedTypeImpl.make(Map.class, new Type[]{String.class, childrenClazz}, null);
Here is nice demo how you can use it in custom deserializer: Deserializing ImmutableList using Gson
You can actually do it. You just need to parse first your data into an JsonArray
and then transform each object individually, and add it to a List
:
Class<T> dataType;
//...
JsonElement root = jsonParser.parse(json);
List<T> data = new ArrayList<>();
JsonArray rootArray = root.getAsJsonArray();
for (JsonElement json : rootArray) {
try {
data.add(gson.fromJson(json, dataType));
} catch (Exception e) {
e.printStackTrace();
}
}
return data;
참고URL : https://stackoverflow.com/questions/20773850/gson-typetoken-with-dynamic-arraylist-item-type
'developer tip' 카테고리의 다른 글
ffmpeg를 사용하여 비디오 중앙에 투명한 워터 마크를 추가하는 방법은 무엇입니까? (0) | 2020.11.14 |
---|---|
PC로 iPad Safari 디버그 (0) | 2020.11.14 |
Java 8에 Scala의 Either와 동등한 것이 있습니까? (0) | 2020.11.14 |
Homebrew는 nvm을 설치하지만 나중에 nvm을 찾을 수 없습니까? (0) | 2020.11.14 |
Keycloak의 OAuth2 / OpenID Connect 엔드 포인트는 무엇입니까? (0) | 2020.11.14 |