android - Format JSON Body for Retrofit from single string value without model -


is there way turn single string value (plain text, not json) json body annotation? not want create such simple model.

example

@post("foo/{fooid}/bars") observable<void> postbar(@path("fooid") string styleid, @body barmodel bar);  class barmodel {     public string bar; } 

will give me expect:

{     "bar" : "hello world" } 

is there simple way annotation? this:

@post("foo/{fooid}/bars") observable<void> postbar(@path("fooid") string styleid, @body("bar") string bar); 

retrofit has converter.factory abstract class can use custom http representation. can create converter construct okhttp.requestbody if method has specific annotation.

the end result like:

@post("/") call<void> postbar(@body @root("bar") string foo) 

and transform: postbar("hello world") { "bar" : "hello world" }.

let's started.

step 1 - create annotation root key (root.java)

/**  * denotes root key of json request.  * <p>  * simple example:  * <pre><code>  * &#64;post("/")  * call&lt;responsebody&gt; example(  *     &#64;root("name") string yourname);  * </code></pre>  * calling {@code foo.example("bob")} yields request body of  * <code>{name=>"bob"}</code>.  * @see jsonconverterfactory  */ @documented @target(parameter) @retention(runtime) public @interface root {   /**    * value of json root.    * results in {"value" : object}    */   string value(); } 

step 2 - define converter.factory detects annotation (jsonconverterfactory.java). i'm using gson json parsing can use whatever framework want.

/**  * converts @root("key") value {"key":json value} using 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) {         (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));         }     } } 

step 3 - install jsonconverterfactory retrofit instance

gson gson = new gsonbuilder().create(); // or customized version retrofit.builder builder = ...; builder.addconverterfactory(new jsonconverterfactory(gson)) 

step 4 - profit

@post("/") call<void> postbar(@body @root("bar") string foo) 

or case:

@post("foo/{fooid}/bars") observable<void> postbar(@body @root("bar") string barvalue, @path("fooid") string styleid); 

Comments

Popular posts from this blog

sequelize.js - Sequelize group by with association includes id -

android - Robolectric "INTERNET permission is required" -

java - Android raising EPERM (Operation not permitted) when attempting to send UDP packet after network connection -