2016-07-06 1 views
5

(jsonではなくプレーンテキスト)を注釈付きJSON本体に変換する方法はありますか?私はそのようなシンプルなモデルを作りたくありません。形式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抽象クラスを持って助けることを願っています -

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); 
    } 
} 

使い方は以下のようになりますカスタムHTTP表現を行います。メソッドに特定のアノテーションがある場合は、コンバータを作成してokhttp.RequestBodyを作成できます。

最終的な結果は次のようになります。

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

と変換:postBar("Hello World"){ "bar" : "Hello World" }に 。

今すぐ始めましょう。

ステップ1 - 注釈(JSONConverterFactory.java)を検出し、あなたのConverter.Factoryを定義する - ルートキー(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のための注釈を作成します。 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 - あなたのレトロフィットインスタンスにJSONConverterFactoryをインストール

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

ステップ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

"コア" retrofitはhttpクライアントです(そしてその$だけですが、コアライブラリにJSONサポートが含まれていることを尋ねましたが、興味がありませんでした)。デザイナーによると、 – Kevin

+0

@ニック、この回答をより良くするための何か他の理由はありますか?まだ受け入れたくない理由はありますか? – Kevin

+0

問題を解決するための1ライナーの解決策があることを望んでいましたこれはあまりにも過剰ですが、他の人を助ける可能性があるので、私はそれを受け入れます –

0

それは必ずしもJSON本体を作成しませんが、あなたのAPIは、URLエンコードされたもの次に

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

ありがとう、試していなかった。私がコントロールしているのはAPIではないので、私が投稿したようなjsonボディを期待している。 (これは私にbar = hello%20worldを与えました) –

+0

あなたはまだそれを試すことができます、これはかなり頻繁に体の代わりに使用することができます。 –

2

Hashmap<String, String>を使用して、より良いで動作することができるかもしれません。 Gsonを使って解析することで、Hashmapを本体に直接渡すことができます。 複数の場所を使用する必要がある場合は、HashMapを拡張した独自のマップを使用できます。そのため、値を1行に追加できます。私は鉱山を掲載しています、それはあなたを助けるかもしれない -

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

が、それは:)

0

this:

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

はまたJsonObject

関連する問題