java - Google Gson-deserialize सूची<class> ऑब्जेक्ट?(सामान्य प्रकार)
json generics (8)
इस पोस्ट का संदर्भ लें। जीएसओएन के लिए तर्क के रूप में जावा टाइप जेनेरिक
मेरे पास इसके लिए बेहतर समाधान है। सूची के लिए रैपर वर्ग यहां है ताकि रैपर बिल्कुल प्रकार की सूची स्टोर कर सके।
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));
}
मैं Google Gson के माध्यम से एक सूची ऑब्जेक्ट को स्थानांतरित करना चाहता हूं, लेकिन मुझे नहीं पता कि जेनेरिक प्रकारों को कैसे deserialize करना है।
मैंने इसे देखने के बाद क्या प्रयास किया (बलुस के जवाब):
MyClass mc = new Gson().fromJson(result, new List<MyClass>(){}.getClass());
लेकिन फिर मुझे ग्रहण में एक त्रुटि मिलती है, "टाइप नई सूची () {} को विरासत में अमूर्त विधि लागू करना होगा ..." और यदि मैं त्वरित सुधार का उपयोग करता हूं तो मुझे 20 से अधिक विधि स्टब्स का राक्षस मिलता है।
मुझे पूरा यकीन है कि एक आसान समाधान है, लेकिन मुझे यह खोजने में असमर्थ लगता है!
संपादित करें:
अब मेरे पास है
Type listType = new TypeToken<List<MyClass>>()
{
}.getType();
MyClass mc = new Gson().fromJson(result, listType);
हालांकि, मुझे "सेजसन" लाइन पर निम्न अपवाद मिलता है:
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 पकड़ता हूं और "परिणाम" शून्य नहीं है।
मैंने सूची की जांच की है डीबगर के साथ टाइप करें और निम्न मिला:
- सूची प्रकार
- args = ListOfTypes
- सूची = शून्य
- हल किया गया प्रकार = प्रकार [1]
- लोडर = PathClassLoader
- मालिक टाइप 0 = शून्य
- मालिक टाइप टाइप = शून्य
- rawType = कक्षा (java.util.ArrayList)
- rawTypeName = "java.util.ArrayList"
- args = ListOfTypes
तो ऐसा लगता है कि "getClass" आमंत्रण ठीक से काम नहीं करता है। कोई सुझाव...?
संपादन 2: मैंने जीसन उपयोगकर्ता मार्गदर्शिका पर जांच की है। यह एक रनटाइम अपवाद का उल्लेख करता है जो जेसन के लिए सामान्य प्रकार को पार्स करने के दौरान होना चाहिए। मैंने इसे "गलत" (उपरोक्त नहीं दिखाया) किया, जैसा कि उदाहरण में था, लेकिन उस अपवाद को बिल्कुल नहीं मिला। तो मैंने सुझाव दिया कि उपयोगकर्ता मार्गदर्शिका में क्रमबद्धता को बदल दिया गया है। हालांकि, मदद नहीं की थी।
संपादित 3: हल, नीचे मेरा जवाब देखें।
एक और तरीका एक सरणी को एक प्रकार के रूप में उपयोग करना है, उदाहरण के लिए:
MyClass[] mcArray = gson.fromJson(jsonString, MyClass[].class);
इस प्रकार आप टाइप ऑब्जेक्ट के साथ सभी परेशानी से बचते हैं, और यदि आपको वास्तव में एक सूची की आवश्यकता है तो आप हमेशा सरणी को एक सूची में परिवर्तित कर सकते हैं:
List<MyClass> mcList = Arrays.asList(mcArray);
आईएमएचओ यह बहुत अधिक पठनीय है।
और इसे एक वास्तविक सूची बनाने के लिए (जिसे संशोधित किया जा सकता है, Arrays.asList()
की सीमाएं देखें) तो बस निम्न कार्य करें:
List<MyClass> mcList = new ArrayList<>(Arrays.asList(mcArray));
चूंकि यह मेरे मूल प्रश्न का उत्तर देता है, मैंने doc_180 के उत्तर को स्वीकार कर लिया है, लेकिन अगर कोई इस समस्या में फिर से चलता है, तो मैं अपने प्रश्न के दूसरे भाग का उत्तर भी दूंगा:
मैंने जो NullPointerError वर्णित किया था, उसके पास सूची के साथ कुछ भी नहीं था, लेकिन इसकी सामग्री के साथ!
"माईक्लास" वर्ग में "नो तर्क" कन्स्ट्रक्टर नहीं था, और न ही इसका सुपरक्लास था। एक बार जब मैंने MyClass और इसके सुपरक्लास में एक सरल "MyClass ()" कन्स्ट्रक्टर जोड़ा, तो सबकुछ ठीक काम करता था, जिसमें सूची क्रमबद्धता और deserialization सहित doc_180 द्वारा सुझाया गया था।
जीसन की 'टाइप' क्लास समझ के लिए उदाहरण 2 का संदर्भ लें।
उदाहरण 1: इस deserilizeResturant में हम कर्मचारी [] सरणी का इस्तेमाल किया और विवरण प्राप्त करें
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());
}
}
मेरे मामले में @ uncaught_exceptions का जवाब काम नहीं किया, मुझे java.lang.reflect.Type
बजाय List.class
का उपयोग करना पड़ा। List.class
करें:
String jsonDuplicatedItems = request.getSession().getAttribute("jsonDuplicatedItems").toString();
List<Map.Entry<Product, Integer>> entries = gson.fromJson(jsonDuplicatedItems, List.class);
मैं एक और संभावना के लिए जोड़ना चाहता हूँ। यदि आप टाइपटोकन का उपयोग नहीं करना चाहते हैं और जेसन ऑब्जेक्ट सरणी को एक ऐरेलिस्ट में कनवर्ट करना चाहते हैं, तो आप इस तरह आगे बढ़ सकते हैं:
यदि आपकी जेसन संरचना इस तरह है:
{
"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 ऑब्जेक्ट के प्रत्येक तत्व तक पहुंच सकते हैं।
वीपी, एक ही परिणाम प्राप्त करने का एक और तरीका। हम इसकी पठनीयता के लिए इसका इस्तेमाल करते हैं।
इस हार्ड-टू-रीड वाक्य को करने के बजाय:
Type listType = new TypeToken<ArrayList<YourClass>>(){}.getType();
List<YourClass> list = new Gson().fromJson(jsonArray, listType);
एक खाली वर्ग बनाएं जो आपकी ऑब्जेक्ट की एक सूची बढ़ाता है:
public class YourClassList extends ArrayList<YourClass> {}
और जेएसओएन पार्स करते समय इसका इस्तेमाल करें:
List<YourClass> list = new Gson().fromJson(jsonArray, YourClassList.class);
सामान्य संग्रह deserialize करने के लिए विधि:
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
ऑब्जेक्ट जावा भाषा में किसी भी प्रकार का प्रतिनिधित्व कर सकता है, जिसमें जेनेरिक प्रकार के पैरामीटरयुक्त इंस्टेंटेशन भी शामिल हैं।
TypeToken
क्लास में सार्वजनिक कन्स्ट्रक्टर नहीं है, क्योंकि आपको इसे सीधे बनाना नहीं है। इसके बजाय, आप हमेशा एक अज्ञात सबक्लास बनाते हैं (इसलिए {}
, जो इस अभिव्यक्ति का एक आवश्यक हिस्सा है)।
टाइप TypeToken
कारण, TypeToken
क्लास केवल उन प्रकारों को कैप्चर करने में सक्षम है जो संकलित समय पर पूरी तरह से ज्ञात हैं। (यानी, आप एक प्रकार पैरामीटर T
लिए new TypeToken<List<T>>() {}.getType()
नहीं कर सकते हैं।)
अधिक जानकारी के लिए, TypeToken
क्लास के लिए प्रलेखन देखें।