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> * @post("/") * call<responsebody> example( * @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
Post a Comment