2015-03-13 9 views
13

मैं JSON संरचना है इस प्रकार की तरह -पुराना वापस gson कनवर्टर

{ 
    "status": true, 
    "message": "Registration Complete.", 
    "data": { 
     "user": { 
      "username": "user88", 
      "email": "[email protected]", 
      "created_on": "1426171225", 
      "last_login": null, 
      "active": "1", 
      "first_name": "User", 
      "last_name": "", 
      "company": null, 
      "phone": null, 
      "sign_up_mode": "GOOGLE_PLUS" 
     } 
    } 
} 

प्रारूप से ऊपर आम है। केवल data कुंजी, user, product तरह की जानकारी के विभिन्न प्रकार के हो सकते हैं invoice आदि

मैं हर बाकी जवाब में एक ही status, message और data कुंजी रखना चाहते हैं। data का इलाज status और message के अनुसार किया जाएगा उपयोगकर्ता को प्रदर्शित किया जाएगा।

तो मूल रूप से, उपरोक्त प्रारूप सभी एपिस में वांछित है। प्रत्येक बार data कुंजी के अंदर की जानकारी प्रत्येक बार अलग होगी।

और मैं सेटअप एक निम्नलिखित वर्ग है और इसे सेट अप gson कनवर्टर के रूप में - MyResponse.java

public class MyResponse<T> implements Serializable{ 
    private boolean status ; 
    private String message ; 
    private T data; 

    public boolean isStatus() { 
     return status; 
    } 

    public void setStatus(boolean status) { 
     this.status = status; 
    } 

    public String getMessage() { 
     return message; 
    } 

    public void setMessage(String message) { 
     this.message = message; 
    } 

    public T getData() { 
     return data; 
    } 

    public void setData(T data) { 
     this.data = data; 
    } 
} 

Deserializer.java

class Deserializer<T> implements JsonDeserializer<T>{ 
    @Override 
    public T deserialize(JsonElement je, Type type, JsonDeserializationContext jdc) throws JsonParseException{ 
     JsonElement content = je.getAsJsonObject(); 

     // Deserialize it. You use a new instance of Gson to avoid infinite recursion to this deserializer 
     return new Gson().fromJson(content, type); 

    } 
} 

और यह प्रयोग किया जाता है इस प्रकार है -

GsonBuilder gsonBuilder = new GsonBuilder(); 
gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES); 
gsonBuilder.registerTypeAdapter(MyResponse.class, new Deserializer<MyResponse>()); 
...... ..... .... 

restBuilder.setConverter(new GsonConverter(gsonBuilder.create())); 

सेवा इंटरफ़ेस इस प्रकार है -

@POST("/register") 
public void test1(@Body MeUser meUser, Callback<MyResponse<MeUser>> apiResponseCallback); 


@POST("/other") 
public void test2(Callback<MyResponse<Product>> apiResponseCallback); 

समस्या

मैं कॉलबैक अंदर से status और message क्षेत्रों तक पहुँच सकते हैं। लेकिन data कुंजी के अंदर की जानकारी पार्स नहीं की गई है और MeUser और Product जैसे मॉडल हमेशा खाली के रूप में लौटते हैं।

मैं कोड ऊपर का पालन करने के json संरचना बदलते हैं पूरी तरह से काम करता है -

{ 
     "status": true, 
     "message": "Registration Complete.", 
     "data": {     
       "username": "user88", 
       "email": "[email protected]", 
       "created_on": "1426171225", 
       "last_login": null, 
       "active": "1", 
       "first_name": "User", 
       "last_name": "", 
       "company": null, 
       "phone": null, 
       "sign_up_mode": "GOOGLE_PLUS" 
     } 
    } 

मैं इसे कैसे data ऑब्जेक्ट के अंदर अलग कुंजी निर्दिष्ट के साथ काम किया है और इसे सफलतापूर्वक पार्स हो सकती है? क्योंकि data विशेषता T जो आप प्रकार MeUser, Product, आदि के होने की उम्मीद के रूप में परिभाषित किया गया है

+0

जानना चाहते हैं कि आप क्या कर रहे हैं –

+0

जीएसओएन सामान्य डेटा प्रकार 'निजी टी डेटा; 'पार्सिंग करते समय ध्यान में न लें। यह कुछ विशिष्ट डेटा प्रकार होना चाहिए। –

+0

'T' के बजाय इस डेटा वर्ग का उपयोग करें।'वर्ग DataClass { \t \t @SerializedName (" उपयोगकर्ता ") उपयोगकर्ता \t \t UserClass; // उपयोगकर्ता वस्तु \t \t @SerializedName (" उत्पाद ") \t \t ProductClass उत्पाद; // उत्पाद वस्तु \t \t @ SerializedName ("चालान") \t \t InvoiceClass चालान; // चालान वस्तु \t \t वर्ग UserClass { \t \t} \t \t वर्ग ProductClass { \t \t} \t \t वर्ग InvoiceClass { \t \t} \t} ' –

उत्तर

22

मैं json में कुछ बदलने के लिए सुझाव है कि कर सकते हैं आप एक नया क्षेत्र है कि डेटा के प्रकार को परिभाषित करता है पर जोड़ने के लिए है कि है, इसलिए json नीचे तरह दिखना चाहिए:

{ 
    "status": true, 
    "message": "Registration Complete.", 
    "dataType" : "user", 
    "data": {     
      "username": "user88", 
      "email": "[email protected]", 
      "created_on": "1426171225", 
      "last_login": null, 
      "active": "1", 
      "first_name": "User", 
      "last_name": "", 
      "company": null, 
      "phone": null, 
      "sign_up_mode": "GOOGLE_PLUS" 
    } 
} 

MyResponse वर्ग नई दायर की है करने के लिए किया गया है DataType कि वह नीचे दिए तरह दिखना चाहिए:

public class MyResponse<T> implements Serializable{ 
    private boolean status ; 
    private String message ; 
    private DataType dataType ; 
    private T data; 


    public DataType getDataType() { 
     return dataType; 
    } 

    //... other getters and setters 
} 

DataType एक enum जो डेटा के प्रकार को परिभाषित करता है। आपको कन्स्ट्रक्टर में पैरामीटर के रूप में Data.class को पास करना होगा। सभी डेटा प्रकारों के लिए आपको नई कक्षाएं बनाना है। DataType enum नीचे तरह दिखना चाहिए:

public enum DataType { 

    @SerializedName("user") 
    USER(MeUser.class), 
    @SerializedName("product") 
    Product(Product.class), 
    //other types in the same way, the important think is that 
    //the SerializedName value should be the same as dataType value from json 
    ; 


    Type type; 

    DataType(Type type) { 
     this.type = type; 
    } 

    public Type getType(){ 
     return type; 
    } 
} 

Json के लिए desarializator चाहिए नीचे दिखाई देता है:

public class DeserializerJson implements JsonDeserializer<MyResponse> { 

    @Override 
    public MyResponse deserialize(JsonElement je, Type type, JsonDeserializationContext jdc) 
      throws JsonParseException { 
     JsonObject content = je.getAsJsonObject(); 
     MyResponse message = new Gson().fromJson(je, type); 
     JsonElement data = content.get("data"); 
     message.setData(new Gson().fromJson(data, message.getDataType().getType())); 
     return message; 

    } 
} 

और जब आप RestAdapter बनाने के लिए, लाइन में जहां Deserializator रजिस्टर, तो आप इस का उपयोग करना चाहिए:

.registerTypeAdapter(MyResponse.class, new DeserializerJson()) 

अन्य कक्षाएं (डेटा के प्रकार) जिन्हें आप अलग-अलग कक्षाओं में जीसन के लिए मानक POJO की तरह परिभाषित करते हैं।

+0

क्या 'सफलता' और 'संदेश' फ़ील्ड के साथ MyResponse.class की ऑब्जेक्ट के रूप में पूरी जेसन प्रतिक्रिया वापस करना संभव है? आईएम गोंबा को स्थिति और संदेश फ़ील्ड के अनुसार संदेश प्रदर्शित करने की आवश्यकता है। अभी यह केवल डेटा कुंजी देता है। बस 'DeserializerJson' सही tweak है ?? – Gimali

+0

ओह। यह वही करता है जो मुझे पहले से चाहिए। महान। मैं जांच करूंगा कि यह अन्य जोंस के साथ भी फिट बैठता है या नहीं। अब साफ और साफ दिखता है। :) – Gimali

+0

क्या आपने मेरा समाधान आजमाया? क्या यह काम करता है जैसा आप चाहते हैं? –

1

आपका मुद्दा है, लेकिन एक वस्तु जो user की तरह भीतरी विशेषता है की वास्तव में है। इसे हल करने के लिए, आपको कक्षाओं का एक और स्तर पेश करने की आवश्यकता है जिसमें आवश्यक गुण user, product, invoice आदि हैं। यह स्थिर आंतरिक कक्षाओं का उपयोग करके आसानी से हासिल किया जा सकता है।

public class MeUser{ 
    private User user; 
    public static class User{ 
    private String username; 
    //add other attributes of the User class 
    } 
} 
+0

क्या कोई ऐसा नहीं है जिसके द्वारा मैं डेटा के अंदर पहली वस्तु का इलाज करने के लिए कनवर्टर बता सकता हूं प्रकार के रूप में और डेटा खुद के रूप में? – Gimali

+0

कोई भी जो मुझे पता है। शायद @ जेकवार्टन समझा सकते हैं। – Rajesh

-1

थोड़ा सा विषय हो सकता है, लेकिन क्या होता है यदि आंतरिक वस्तु में दिनांक संपत्ति होती है? मेरे TypeAdapter इस तरह दिखता है:

.registerTypeAdapter(Date.class, new DateDeserializer()) 
       .registerTypeAdapter(GenericNotificationResponse.class, new NotificationDeserializer()) 
       .setDateFormat("yyyy-MM-dd'T'HH:mm:ss") 
       .create(); 

लेकिन पार्स जो इस द्वारा किया जाता है की वजह से: message.setData(new Gson().fromJson(data, message.getDataType().getType()));

यह जब भी यह तिथि संपत्ति deserialize करने की कोशिश करेंगे एक त्रुटि फेंक देते हैं। क्या इसके लिए कोई त्वरित समाधान है?

संपादित करें: उत्तर को स्वीकार्य रूप से चिह्नित किया गया है, निश्चित रूप से :) इससे मुझे मेरी समस्या को ठीक करने में मदद मिली। लेकिन अब तारीख deserializer के साथ इस समस्या है।