2016-07-06 5 views
5

क्या एक सिंगल स्ट्रिंग मान (सादा पाठ, जेसन नहीं) एक एनोटेशन के साथ एक JSON बॉडी में बदलने का कोई तरीका है? मैं इतना सरल मॉडल नहीं बनाना चाहता हूं।मॉडल के बिना एकल स्ट्रिंग मान से रेट्रोफिट के लिए जेएसओएन बॉडी प्रारूप

उदाहरण

@POST("foo/{fooId}/bars") 
Observable<Void> postBar(@Path("fooId") String styleId, @Body BarModel bar); 

class BarModel { 
    public String bar; 
} 

मुझे दे देगा मैं क्या उम्मीद:

{ 
    "bar" : "hello world" 
} 

वहाँ एक टिप्पणी के साथ यह करने के लिए एक आसान तरीका है? कुछ इस तरह:

@POST("foo/{fooId}/bars") 
Observable<Void> postBar(@Path("fooId") String styleId, @Body("bar") String bar); 
+0

भी देखें इस [मेटा-चर्चा] (http://meta.stackoverflow.com/q/327487/230513) में मानचित्र बदल जाएगा। – trashgod

उत्तर

7

रेट्रोफिट एक Converter.Factory सार वर्ग है कि आप करने के लिए उपयोग कर सकते हैं में मदद मिलेगी कस्टम HTTP प्रतिनिधित्व करते हैं। यदि विधि में एक विशिष्ट एनोटेशन है तो आप okhttp.RequestBody बनाने के लिए कनवर्टर बना सकते हैं।

अंतिम परिणाम तरह दिखेगा:

@POST("/") 
Call<Void> postBar(@Body @Root("bar") String foo) 

और परिणत: postBar("Hello World") { "bar" : "Hello World" } में।

चलो शुरू करें।

चरण 1 - जड़ कुंजी (Root.java)

/** 
* Denotes the root key of a JSON request. 
* <p> 
* Simple Example: 
* <pre><code> 
* &#64;POST("/") 
* Call&lt;ResponseBody&gt; example(
*  &#64;Root("name") String yourName); 
* </code></pre> 
* Calling with {@code foo.example("Bob")} yields a request body of 
* <code>{name=>"Bob"}</code>. 
* @see JSONConverterFactory 
*/ 
@Documented 
@Target(PARAMETER) 
@Retention(RUNTIME) 
public @interface Root { 
    /** 
    * The value of the JSON root. 
    * Results in {"value" : object} 
    */ 
    String value(); 
} 

चरण 2 के लिए एक एनोटेशन बना सकते हैं - अपने Converter.Factory कि एनोटेशन (JSONConverterFactory.java) का पता लगाता है परिभाषित करते हैं। मैं JSON पार्सिंग के लिए Gson का उपयोग कर रहा हूं लेकिन आप जो भी ढांचा चाहते हैं उसका उपयोग कर सकते हैं।

/** 
* Converts @Root("key") Value to {"key":json value} using the provided Gson converter. 
*/ 
class JSONConverterFactory extends Converter.Factory { 
    private final Gson gson; 
    private static final MediaType CONTENT_TYPE = 
      MediaType.parse("application/json"); 

    JSONConverterFactory(Gson gson) { 
     this.gson = gson; 
    } 

    @Override 
    public Converter<?, RequestBody> requestBodyConverter(
      Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) { 
     for (Annotation annotation : parameterAnnotations) { 
      if (annotation instanceof Root) { 
       Root rootAnnotation = (Root) annotation; 
       return new JSONRootConverter<>(gson, rootAnnotation.value()); 
      } 
     } 
     return null; 
    } 

    private final class JSONRootConverter<T> implements Converter<T, RequestBody> { 
     private Gson gson; 
     private String rootKey; 

     private JSONRootConverter(Gson gson, String rootKey) { 
      this.gson = gson; 
      this.rootKey = rootKey; 
     } 

     @Override 
     public RequestBody convert(T value) throws IOException { 
      JsonElement element = gson.toJsonTree(value); 
      JsonObject object = new JsonObject(); 
      object.add(this.rootKey, element); 
      return RequestBody.create(CONTENT_TYPE, this.gson.toJson(object)); 
     } 
    } 
} 

चरण 3 - अपने रेट्रोफिट उदाहरण

Gson gson = new GsonBuilder().create(); // Or your customized version 
Retrofit.Builder builder = ...; 
builder.addConverterFactory(new JSONConverterFactory(gson)) 

चरण में JSONConverterFactory स्थापित 4 - लाभ

@POST("/") 
Call<Void> postBar(@Body @Root("bar") String foo) 

या अपने मामले के लिए:

@POST("foo/{fooId}/bars") 
Observable<Void> postBar(@Body @Root("bar") String barValue, @Path("fooId") String styleId); 
+0

"कोर" रेट्रोफिट एक http क्लाइंट है (और केवल $। मैंने कोर लाइब्रेरी में बेहतर JSON समर्थन सहित उनसे पूछा था और उन्हें कोई दिलचस्पी नहीं थी। रेट्रोफिट स्पष्ट रूप से विस्तारित करने के लिए डिज़ाइन किया गया था, इसलिए यह "सही" दृष्टिकोण है डिजाइनरों के मुताबिक। – Kevin

+0

@ निक, क्या कोई और चीज है जो इस उत्तर को बेहतर करेगी/किसी भी कारण से आप इसे स्वीकार नहीं करना चाहते हैं? – Kevin

+0

मैं उम्मीद कर रहा था कि मेरी समस्या का विस्तार करने के लिए एक लाइनर समाधान होगा यह बहुत अधिक है। हालांकि मैं इसे स्वीकार करूंगा क्योंकि यह दूसरों की मदद करने की संभावना है –

0

यह जरूरी एक json शरीर का निर्माण नहीं करता है, लेकिन अपने API URL इनकोडिंग बातें

@FormUrlEncoded 
@POST("foo/{fooId}/bars") 
Observable<Void> postBar(@Path("fooId") String styleId, @Field("bar") String bar); 
+0

धन्यवाद, कोशिश नहीं की थी। यह एक एपीआई नहीं है जिस पर मेरा नियंत्रण है, इसलिए एक जेसन बॉडी की तरह मैं एक पोस्ट की उम्मीद कर रहा हूं। (इसने मुझे बार = हैलो% 20 वर्ल्ड) –

+0

दिया है, आप अभी भी इसे आजमा सकते हैं, इसका उपयोग अक्सर शरीर के बजाय किया जा सकता है। –

2

फिर Hashmap<String, String> उपयोग करने के लिए बेहतर के साथ काम करने में सक्षम हो सकता है। आप जीसन का उपयोग करके पार्सिंग करके सीधे शरीर में हैशमैप पास कर सकते हैं। और यदि आपको एकाधिक जगह का उपयोग करने की आवश्यकता है तो आप अपने मानचित्र का उपयोग हैश मैप को विस्तारित कर सकते हैं, ताकि आप अपने मान एक पंक्ति में जोड़ सकें। मैं मेरा पोस्टिंग कर रहा हूँ, यह आपकी मदद कर सकता है -

public class PostParams extends HashMap<String, String> { 
    public static PostParams init() { 
     return new PostParams(); 
    } 

    public PostParams add(String param, String value) { 
     put(param, value); 
     return this; 
    } 

    public PostParams add(String param, String[] values) { 
     put(param, new Gson().toJson(values)); 
     return this; 
    } 

    public PostParams add(String param, int[] values) { 
     put(param, new Gson().toJson(values)); 
     return this; 
    } 

    public PostParams add(String param, int value) { 
     put(param, value + ""); 
     return this; 
    } 

    public PostParams addPlatform() { 
     put("Platform", Constants.ANDROID); 
     return this; 
    } 

    public PostParams add(String param, double value) { 
     put(param, new Gson().toJson(value)); 
     return this; 
    } 

    @Override 
    public String toString() { 
     return new Gson().toJson(this); 
    } 
} 

प्रयोग किया जाएगा -

String postData = new PostParams().add("bar", "Hello World").toString() 

आशा है कि यह :)

0

मैं की तरह उपयोग करें यह:

@POST("url") 
Observable<Response<Object>> login(@Body Map<String, Object> body); 

यह JSONObject

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