Google Gson-역 직렬화 목록목적? (일반 타입)
Google Gson을 통해 목록 객체를 전송하고 싶지만 일반 유형을 역 직렬화하는 방법을 모르겠습니다.
이것을 보고 난 후에 시도한 것 (BalusC의 답변) :
MyClass mc = new Gson().fromJson(result, new List<MyClass>(){}.getClass());
그러나 "새 List () {} 형식은 상속 된 추상 메서드를 구현해야합니다 ..."라는 식의 오류가 발생합니다. 빠른 수정을 사용하면 20 개가 넘는 메서드 스텁의 몬스터가 생깁니다.
더 쉬운 해결책이 있다고 확신하지만 찾을 수없는 것 같습니다!
편집하다:
지금 나 한테있어
Type listType = new TypeToken<List<MyClass>>()
{
}.getType();
MyClass mc = new Gson().fromJson(result, listType);
그러나 "fromJson"줄에서 다음 예외가 발생합니다.
java.lang.NullPointerException
at org.apache.harmony.luni.lang.reflect.ListOfTypes.length(ListOfTypes.java:47)
at org.apache.harmony.luni.lang.reflect.ImplForType.toString(ImplForType.java:83)
at java.lang.StringBuilder.append(StringBuilder.java:203)
at com.google.gson.JsonDeserializerExceptionWrapper.deserialize(JsonDeserializerExceptionWrapper.java:56)
at com.google.gson.JsonDeserializationVisitor.invokeCustomDeserializer(JsonDeserializationVisitor.java:88)
at com.google.gson.JsonDeserializationVisitor.visitUsingCustomHandler(JsonDeserializationVisitor.java:76)
at com.google.gson.ObjectNavigator.accept(ObjectNavigator.java:106)
at com.google.gson.JsonDeserializationContextDefault.fromJsonArray(JsonDeserializationContextDefault.java:64)
at com.google.gson.JsonDeserializationContextDefault.deserialize(JsonDeserializationContextDefault.java:49)
at com.google.gson.Gson.fromJson(Gson.java:568)
at com.google.gson.Gson.fromJson(Gson.java:515)
at com.google.gson.Gson.fromJson(Gson.java:484)
at com.google.gson.Gson.fromJson(Gson.java:434)
내가 할 캐치 JsonParseExceptions 및 "결과를"null이 아닙니다.
디버거로 listType을 확인하고 다음을 얻었습니다.
- 목록 유형
- args = ListOfTypes
- 목록 = null
- resolvedTypes = 유형 [1]
- 로더 = PathClassLoader
- ownerType0 = null
- ownerTypeRes = null
- rawType = 클래스 (java.util.ArrayList)
- rawTypeName = "java.util.ArrayList"
- args = ListOfTypes
"getClass"호출이 제대로 작동하지 않은 것 같습니다. 어떤 제안 ...?
Edit2 : Gson User Guide 에서 확인했습니다 . 제네릭 형식을 Json으로 구문 분석하는 동안 발생하는 런타임 예외에 대해 설명합니다. 예제에서와 같이 "잘못된"(위에 표시되지 않음) 작업을 수행했지만 해당 예외를 전혀 얻지 못했습니다. 따라서 사용자 안내서에서 제안한대로 직렬화를 변경했습니다. 그래도 도움이되지 않았습니다.
편집 3 : 해결되었습니다. 아래 답변을 참조하십시오.
일반 컬렉션을 역 직렬화하는 방법 :
import java.lang.reflect.Type;
import com.google.gson.reflect.TypeToken;
...
Type listType = new TypeToken<ArrayList<YourClass>>(){}.getType();
List<YourClass> yourClassList = new Gson().fromJson(jsonArray, listType);
의견에 여러 사람들이 언급 했으므로 다음은 TypeToken
수업이 어떻게 사용 되는지에 대한 설명입니다 . 구조는 new TypeToken<...>() {}.getType()
컴파일 시간 유형 (사이 캡처 <
및 >
런타임으로) java.lang.reflect.Type
객체. Class
원시 (삭제 된) 유형 만 나타낼 수 있는 객체 와 달리 객체 Type
는 일반 유형의 매개 변수화 된 인스턴스화를 포함하여 Java 언어의 모든 유형을 나타낼 수 있습니다.
TypeToken
당신이 직접 구성 안하고 있기 때문에 클래스 자체는, public 생성자가 없습니다. 대신 항상 익명 서브 클래스를 구성합니다 (따라서이 {}
표현식의 필수 부분 임).
유형 삭제로 인해 TypeToken
클래스는 컴파일 타임에 완전히 알려진 유형 만 캡처 할 수 있습니다. 즉, new TypeToken<List<T>>() {}.getType()
type 매개 변수 는 수행 할 수 없습니다 T
.
자세한 내용 은 해당 TypeToken
클래스 의 설명서를 참조하십시오 .
또 다른 방법은 배열을 유형으로 사용하는 것입니다. 예 :
MyClass[] mcArray = gson.fromJson(jsonString, MyClass[].class);
이렇게하면 Type 객체로 인한 번거 로움을 피할 수 있으며 실제로 목록이 필요한 경우 항상 다음을 통해 배열을 목록으로 변환 할 수 있습니다.
List<MyClass> mcList = Arrays.asList(mcArray);
IMHO 이것은 훨씬 더 읽기 쉽습니다.
그리고 실제 목록 (수정 가능, 제한 사항 참조 Arrays.asList()
)으로 만들려면 다음을 수행하십시오.
List<MyClass> mcList = new ArrayList<>(Arrays.asList(mcArray));
이 게시물을 참조하십시오. GSON의 인수로 Java 유형 일반
이에 대한 더 나은 해결책이 있습니다. 다음은 목록에 대한 래퍼 클래스입니다. 래퍼는 정확한 유형의 목록을 저장할 수 있습니다.
public class ListOfJson<T> implements ParameterizedType
{
private Class<?> wrapped;
public ListOfJson(Class<T> wrapper)
{
this.wrapped = wrapper;
}
@Override
public Type[] getActualTypeArguments()
{
return new Type[] { wrapped };
}
@Override
public Type getRawType()
{
return List.class;
}
@Override
public Type getOwnerType()
{
return null;
}
}
그런 다음 코드는 간단 할 수 있습니다.
public static <T> List<T> toList(String json, Class<T> typeClass)
{
return sGson.fromJson(json, new ListOfJson<T>(typeClass));
}
같은 결과를 얻는 또 다른 방법 인 Wep. 가독성을 위해 사용합니다.
이 읽기 어려운 문장을 수행하는 대신 :
Type listType = new TypeToken<ArrayList<YourClass>>(){}.getType();
List<YourClass> list = new Gson().fromJson(jsonArray, listType);
객체의 목록을 확장하는 빈 클래스를 만듭니다.
public class YourClassList extends ArrayList<YourClass> {}
JSON을 구문 분석 할 때 사용하십시오.
List<YourClass> list = new Gson().fromJson(jsonArray, YourClassList.class);
이후 Gson 2.8
, 우리는 다음과 같은 유틸리티 함수를 만들 수 있습니다
public <T> List<T> getList(String jsonArray, Class<T> clazz) {
Type typeOfT = TypeToken.getParameterized(List.class, clazz).getType();
return new Gson().fromJson(jsonArray, typeOfT);
}
사용 예
String jsonArray = ...
List<User> user = getList(jsonArray, User.class);
public static final <T> List<T> getList(final Class<T[]> clazz, final String json)
{
final T[] jsonToObject = new Gson().fromJson(json, clazz);
return Arrays.asList(jsonToObject);
}
예:
getList(MyClass[].class, "[{...}]");
원래 질문에 대한 답변으로 doc_180의 답변을 수락했지만 누군가이 문제가 다시 발생하면 내 질문의 후반에도 답변합니다.
내가 설명한 NullPointerError는 List 자체와 관련이 없지만 그 내용과 관련이 있습니다!
"MyClass"클래스에는 "args 없음"생성자가없고 수퍼 클래스 클래스도 없습니다. 간단한 "MyClass ()"생성자를 MyClass 및 해당 수퍼 클래스에 추가하면 doc_180에서 제안한대로 목록 직렬화 및 역 직렬화를 포함하여 모든 것이 제대로 작동했습니다.
코 틀린의 경우 :
import java.lang.reflect.Type
import com.google.gson.reflect.TypeToken
...
val type = object : TypeToken<ArrayList<T>>() {}.type
또는 다음은 유용한 기능입니다.
fun <T> buildType(): Type {
return object : TypeToken<ArrayList<T>>() {}.type
}
그런 다음 사용하십시오.
val type = buildType<YourMagicObject>()
다음은 동적으로 정의 된 유형으로 작동하는 솔루션입니다. 요령은 Array.newInstance ()를 사용하여 적절한 유형의 배열을 만드는 것입니다.
public static <T> List<T> fromJsonList(String json, Class<T> clazz) {
Object [] array = (Object[])java.lang.reflect.Array.newInstance(clazz, 0);
array = gson.fromJson(json, array.getClass());
List<T> list = new ArrayList<T>();
for (int i=0 ; i<array.length ; i++)
list.add(clazz.cast(array[i]));
return list;
}
하나 더 가능성을 추가하고 싶습니다. TypeToken을 사용하지 않고 json 객체 배열을 ArrayList로 변환하려면 다음과 같이 진행하십시오.
json 구조가 다음과 같은 경우 :
{
"results": [
{
"a": 100,
"b": "value1",
"c": true
},
{
"a": 200,
"b": "value2",
"c": false
},
{
"a": 300,
"b": "value3",
"c": true
}
]
}
수업 구조는 다음과 같습니다.
public class ClassName implements Parcelable {
public ArrayList<InnerClassName> results = new ArrayList<InnerClassName>();
public static class InnerClassName {
int a;
String b;
boolean c;
}
}
그런 다음 다음과 같이 구문 분석 할 수 있습니다.
Gson gson = new Gson();
final ClassName className = gson.fromJson(data, ClassName.class);
int currentTotal = className.results.size();
이제 className 객체의 각 요소에 액세스 할 수 있습니다.
Gson의 '유형'클래스 이해에 대해서는 예 2를 참조하십시오.
예제 1 :이 deserilizeResturant에서 Employee [] 배열을 사용하여 세부 사항을 얻었습니다.
public static void deserializeResturant(){
String empList ="[{\"name\":\"Ram\",\"empId\":1},{\"name\":\"Surya\",\"empId\":2},{\"name\":\"Prasants\",\"empId\":3}]";
Gson gson = new Gson();
Employee[] emp = gson.fromJson(empList, Employee[].class);
int numberOfElementInJson = emp.length();
System.out.println("Total JSON Elements" + numberOfElementInJson);
for(Employee e: emp){
System.out.println(e.getName());
System.out.println(e.getEmpId());
}
}
예 2 :
//Above deserilizeResturant used Employee[] array but what if we need to use List<Employee>
public static void deserializeResturantUsingList(){
String empList ="[{\"name\":\"Ram\",\"empId\":1},{\"name\":\"Surya\",\"empId\":2},{\"name\":\"Prasants\",\"empId\":3}]";
Gson gson = new Gson();
// Additionally we need to se the Type then only it accepts List<Employee> which we sent here empTypeList
Type empTypeList = new TypeToken<ArrayList<Employee>>(){}.getType();
List<Employee> emp = gson.fromJson(empList, empTypeList);
int numberOfElementInJson = emp.size();
System.out.println("Total JSON Elements" + numberOfElementInJson);
for(Employee e: emp){
System.out.println(e.getName());
System.out.println(e.getEmpId());
}
}
kays1의 답변을 좋아했지만 구현할 수 없었습니다. 그래서 나는 그의 개념을 사용하여 나만의 버전을 만들었습니다.
public class JsonListHelper{
public static final <T> List<T> getList(String json) throws Exception {
Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create();
Type typeOfList = new TypeToken<List<T>>(){}.getType();
return gson.fromJson(json, typeOfList);
}
}
용법:
List<MyClass> MyList= JsonListHelper.getList(jsonArrayString);
내 경우에는 @uncaught_exceptions의 답변이 효과가 없었습니다. List.class
대신에 사용해야 했습니다 java.lang.reflect.Type
.
String jsonDuplicatedItems = request.getSession().getAttribute("jsonDuplicatedItems").toString();
List<Map.Entry<Product, Integer>> entries = gson.fromJson(jsonDuplicatedItems, List.class);
참고 URL : https://stackoverflow.com/questions/5554217/google-gson-deserialize-listclass-object-generic-type
'Programming' 카테고리의 다른 글
문자열의 첫 글자를 대문자로 만듭니다 (성능 극대화). (0) | 2020.02.21 |
---|---|
Android에서 텍스트를 굵게 변경하려면 어떻게합니까? (0) | 2020.02.21 |
Gson : 주석없이 직렬화에서 특정 필드를 제외하는 방법 (0) | 2020.02.21 |
Python 오류“ImportError : No module named” (0) | 2020.02.21 |
오류 : xxx를 'this'인수로 xxx를 전달하면 한정자를 버립니다. (0) | 2020.02.21 |