2012-07-25 21 views
11

Deserialize मैंने गलत सवाल पोस्ट किया था। मैं यहां प्रश्न सही तरीके से पोस्ट कर रहा हूं ...जैक्सन - जेनेरिक क्लास वेरिएबल

मुझे एक HTTP प्रतिक्रिया के रूप में एक जेसन स्ट्रिंग मिल रही है। मैं इसकी संरचना जानता हूं। यह निम्नानुसार है:

public class Json<T> { 
    public Hits<T> hits; 
} 
public class Hits<T> { 
    public int found; 
    public int start; 
    public ArrayList<Hit<T>> hit; 
} 
public class Hit<T> { 
    public String id; 
    public Class<T> data; 
} 

"डेटा" फ़ील्ड किसी भी वर्ग से संबंधित हो सकता है। मैं इसे केवल रनटाइम पर ही जानूंगा। मैं इसे पैरामीटर के रूप में प्राप्त करूंगा। इस तरह मैं deserializing हूँ।

java.lang.class से निजी java.lang.class.Class() का उपयोग नहीं कर सकते हैं -

public <T> void deSerialize(Class<T> clazz) { 
    ObjectMapper mapper = new ObjectMapper(); 
    mapper.readValue(jsonString, new TypeReference<Json<T>>() {}); 
} 

लेकिन मैं एक त्रुटि हो रही है। पहुंच सेट करने में विफल। Java.lang.Class कन्स्ट्रक्टर को सुलभ नहीं कर सकता

+0

प्रश्न क्यों डुप्लिकेट करना (देखें http://stackoverflow.com/questions/11664894/jackson-deserialize-using-generic-class/11681540)? – StaxMan

+0

देखें http://stackoverflow.com/questions/17400850/is-jackson-really-unable-to-deserialize-json-into-a-generic-type – lisak

उत्तर

1

आप क्लास ऑब्जेक्ट को JSON पर क्रमबद्ध और deserializing कर रहे हैं? हो सकता है कि इसे हिट में स्ट्रिंग के रूप में रखें और अतिरिक्त गेटर बनाएं जो Class.forName लॉन्च करता है, उदा।

public class Hit { 
    public String id; 
    public String data; 
    public Class<?> getDataClass() throws Exception { 
     return Class.forName(data); 
    } 
} 
+0

मैंने सवाल पूरी तरह से संपादित किया है, क्या आप इसका उत्तर दे सकते हैं? – gnjago

+1

आपको मिली त्रुटि में कहा गया है: "मैं नई कक्षा वस्तु को इंस्टाल करना चाहता हूं लेकिन मैं 'नई कक्षा()' निष्पादित नहीं कर सकता क्योंकि निर्माता निजी है "। इसका कोई मतलब नहीं है। कृपया नमूना JSON स्ट्रिंग डालें। तब समाधान का सुझाव देना बहुत आसान होगा। मुझे पूरा यकीन है कि प्रकार वर्ग की धारावाहिक/deserializing संपत्ति एक गलत रास्ता है। –

0

deserialize जेनेरिक वर्ग चर

...

मैं इसे कैसे जैक्सन को बताऊँ? क्या जीसन बेहतर होगा?

The Gson user guide includes a section बिल्कुल जो मैं समझता हूं कि आप इसे पूरा करने की कोशिश कर रहे हैं, हालांकि यह दस्तावेज उदाहरण अभी भी अधूरा हो सकता है।

In a blog post, I covered in more detail the solution using Gson 1.7.1. नीचे प्रासंगिक कोड उदाहरण है।

जैक्सन (1.8.2) का उपयोग कर समान (लेकिन अधिक शामिल) समाधान भी उसी ब्लॉग पोस्ट में प्रदर्शित और वर्णित हैं। (अलग दृष्टिकोण और उदाहरण कोड की लाइनों के सैकड़ों का उपयोग करें, तो मैं उन्हें यहाँ reposting हटा दिया है।)

public class GsonInstanceCreatorForParameterizedTypeDemo 
{ 
public static void main(String[] args) 
{ 
    Id<String> id1 = new Id<String>(String.class, 42); 

    Gson gson = new GsonBuilder().registerTypeAdapter(Id.class, 
    new IdInstanceCreator()).create(); 
    String json1 = gson.toJson(id1); 
    System.out.println(json1); 
    // actual output: {"classOfId":{},"value":42} 
    // This contradicts what the Gson docs say happens. 
    // With custom serialization, as described in a 
    // previous Gson user guide section, 
    // intended output may be 
    // {"value":42} 

    // input: {"value":42} 
    String json2 = "{\"value\":42}"; 

    Type idOfStringType=new TypeToken<Id<String>>(){}.getType(); 
    Id<String> id1Copy = gson.fromJson(json2, idOfStringType); 
    System.out.println(id1Copy); 
    // output: classOfId=class java.lang.String, value=42 

    Type idOfGsonType = new TypeToken<Id<Gson>>() {}.getType(); 
    Id<Gson> idOfGson = gson.fromJson(json2, idOfGsonType); 
    System.out.println(idOfGson); 
    // output: classOfId=class com.google.gson.Gson, value=42 
} 
} 

class Id<T> 
{ 
private final Class<T> classOfId; 
private final long value; 

public Id(Class<T> classOfId, long value) 
{ 
    this.classOfId = classOfId; 
    this.value = value; 
} 

@Override 
public String toString() 
{ 
    return "classOfId=" + classOfId + ", value=" + value; 
} 
} 

class IdInstanceCreator implements InstanceCreator<Id<?>> 
{ 
@SuppressWarnings({ "unchecked", "rawtypes" }) 
public Id<?> createInstance(Type type) 
{ 
    Type[] typeParameters = 
    ((ParameterizedType) type).getActualTypeArguments(); 
    Type idType = typeParameters[0]; 
    return new Id((Class<?>) idType, 0L); 
} 
} 
10

आप JavaType स्पष्ट रूप से निर्माण करने के लिए, अगर सामान्य प्रकार केवल गतिशील रूप से उपलब्ध है की आवश्यकता होगी:

// do NOT create new ObjectMapper per each request! 
final ObjectMapper mapper = new ObjectMapper(); 

public Json<T> void deSerialize(Class<T> clazz, InputStream json) { 
    return mapper.readValue(json, 
     mapper.getTypeFactory().constructParametricType(Json.class, clazz)); 
} 
+0

यह मेरे अनुभव से काम नहीं करता है, हालांकि यह एक बग हो सकता है: https://github.com/FasterXML/jackson-databind/issues/254 – lisak

+0

संदर्भित बग में अन्य समस्याएं थीं - सामान्य प्रकार का संकल्प दिखाया गया है उपरोक्त काम करेगा, लेकिन अन्य संभावित समस्याओं का समाधान नहीं करता है। – StaxMan

+0

हाँ, मेरी माफ़ी, इसे यहां हल किया गया है http://stackoverflow.com/questions/17400850/is-jackson-really-unable-to-deserialize-json-into-a-generic-type – lisak

2

नमूना सामान्य deserializing इंटरफ़ेस:

public interface Deserializable<T> { 
    static final ObjectMapper mapper = new ObjectMapper(); 

    @SuppressWarnings("unchecked") 
    default T deserialize(String rawJson) throws IOException { 
     return mapper.readValue(rawJson, (Class<T>) this.getClass()); 
    } 
} 
0

JSON स्ट्रिंग deserialized किए जाने की जरूरत है कि paramet के बारे में जानकारी होती है प्रकार करना होगा एर T
आपको प्रत्येक वर्ग पर जैक्सन एनोटेशन देना होगा जिसे पैरामीटर T कक्षा Json पर पारित किया जा सकता है ताकि पैरामीटर प्रकार T के बारे में प्रकार की जानकारी जैक्सन द्वारा जेएसओएन स्ट्रिंग से लिखी/लिखी जा सके।

मान लीजिए कि T कोई वर्ग हो सकता है जो अमूर्त वर्ग Result फैलाता है।

public class Json<T extends Result> { 
    public Hits<T> hits; 
} 

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.WRAPPER_OBJECT) 
@JsonSubTypes({ 
     @JsonSubTypes.Type(value = ImageResult.class, name = "ImageResult"), 
     @JsonSubTypes.Type(value = NewsResult.class, name = "NewsResult")}) 
public abstract class Result { 

} 

public class ImageResult extends Result { 

} 

public class NewsResult extends Result { 

} 

एक बार वर्ग (या उनके आम महाप्रकार) पैरामीटर T के रूप में पारित किया जा सकता है कि में से प्रत्येक टिप्पणी की जाती है, जैक्सन JSON में पैरामीटर T के बारे में जानकारी शामिल होंगे।ऐसे JSON को संकलन समय पर पैरामीटर T जानने के बिना deserialized किया जा सकता है।
यह Jackson documentation link पॉलिमॉर्फिक deserialization के बारे में बात करता है लेकिन इस सवाल के लिए भी उपयोगी है।

संबंधित मुद्दे