2016-10-19 1 views
1

Ich versuche, das folgende Java-Modell als Form codiert Körper OHNE die Umhüllung {} zu senden. Ich habe alles versucht, ich kann NICHT als JSON ein Modell senden finden, sondern als Form codierten Daten Retrofit mit 2.Retrofit 2 - Senden Modell in @Body als Formdata NICHT als JSON

// Sends as JSON 
@Headers("Content-Type:application/x-www-form-urlencoded") 
@POST(SERVICES + USERS) 
Observable<UserInfoResponse> signupUser(@Body SignUpParams params); 

// Works 
@FormUrlEncoded 
@POST(SERVICES + USERS) 
Observable<UserInfoResponse> signupUser(
     @Field("approve") boolean approve, 
     @Field("daily_newsletter") int newsletter, 
     @Field("include_order_info") boolean includeOrderInfo, 
     @Field("is_21") int is21, 
     @Field("is_guest") int isGuest, 
     @Field("method") String method, 
     @Field("email") String email, 
     @Field("password") String password, 
     @Field("oauth_token") String oauthToken 
); 

Hier unser Setup ist, wenn es

// Dagger Provider 
@Provides 
@Singleton 
@Named(JT_API) 
Retrofit provideJTSecureApiRetrofit(OkHttpClient okHttpClient, Gson gson) { 
    Retrofit retrofit = new Retrofit.Builder().client(okHttpClient) 
      .baseUrl(jtBaseUrl) 
      .addConverterFactory(GsonConverterFactory.create(gson)) 
      .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 
      .build(); 
    return retrofit; 
} 

@Provides 
@Singleton 
OkHttpClient provideOkHttpClient(JTApp app) { 
    Interceptor addUrlParams = chain -> { 
     Request request = chain.request(); 
     HttpUrl url = request.url() 
      .newBuilder() 
      .addQueryParameter("app_version", BuildConfig.VERSION_NAME) 
      .build(); 

     request = request.newBuilder() 
      .url(url) 
      .build(); 
     return chain.proceed(request); 
    }; 

    OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder(); 

    okHttpClientBuilder.addInterceptor(addUrlParams); 

    // this doesn't seem to do anything… 
    okHttpClientBuilder.addInterceptor(chain -> { 
     Request original = chain.request(); 

     Request.Builder requestBuilder = original.newBuilder() 
       .addHeader("Content-Type", "application/x-www-form-urlencoded"); 

     Request request = requestBuilder.build(); 

     return chain.proceed(request); 
    }); 

    okHttpClientBuilder.readTimeout(JTApp.HTTP_TIMEOUT, TimeUnit.SECONDS) 
      .connectTimeout(JTApp.HTTP_TIMEOUT, TimeUnit.SECONDS); 

    return okHttpClientBuilder.build(); 
} 
+0

Das Problem ist unklar. Versuchen Sie, das Modell als JSON ohne Erfolg zu senden? –

+0

Warum setzen Sie '' Content-Type: application/x-www-form-urlencoded "' Header mit JSON? –

+1

Bitte lesen Sie die Anweisungen unter https://square.github.io/retrofit/ –

Antwort

0

hilft, wenn ich nicht bin

irrt

Für application/x-www-form-urlencoded, der Körper der HTTP-Nachricht an den Server gesendet wird, ist im wesentlichen ein Riesen-Query-String - Name/Wert Paare sind durch das kaufmännische Und getrennt (&), und Namen werden von Werte durch das Gleichheitszeichen (=) getrennt.

How to send Form data in retrofit2 android

+0

Leider haben sie das gegenteilige Problem von mir. Retrofit sendet es als JSON, wenn es als formcodierte Daten gesendet werden soll. Wenn Sie die Kopfzeile hinzufügen, wird sie in eine riesige Abfragezeichenfolge konvertiert, wie es in Ihrer Definition heißt –

0

Stellt sich heraus, ich meine eigenen Schlüsselwertpaar-Wandler zu schaffen hatte, die die Retrofit2 Converter.Factory

/** 
* Retrofit 2 Key Value Pair Form Data Encoder 
* 
* This is a copy over of {@link GsonConverterFactory}. This class sends the outgoing response as 
* form data vs the gson converter which sends it as JSON. The response is proxied through the 
* gson converter factory just the same though 
* 
* Created by marius on 11/17/16. 
*/ 
public class RF2_KeyValuePairConverter extends Converter.Factory { 

    private final GsonConverterFactory gsonConverter; 

    /** 
    * Create an instance using a default {@link Gson} instance for conversion. Encoding to form data and 
    * decoding from JSON (when no charset is specified by a header) will use UTF-8. 
    */ 
    public static RF2_KeyValuePairConverter create() { 
     return create(new Gson()); 
    } 

    /** 
    * Create an instance using {@code gson} for conversion. Encoding to Form data and 
    * decoding from JSON (when no charset is specified by a header) will use UTF-8. 
    */ 
    public static RF2_KeyValuePairConverter create(Gson gson) { 
     return new RF2_KeyValuePairConverter(gson); 
    } 

    private final Gson gson; 

    private RF2_KeyValuePairConverter(Gson gson) { 
     if (gson == null) throw new NullPointerException("gson == null"); 
     this.gson = gson; 

     this.gsonConverter = GsonConverterFactory.create(gson); 
    } 

    @Override 
    public Converter<ResponseBody, ?> responseBodyConverter(Type type, Annotation[] annotations, 
                  Retrofit retrofit) { 
     return gsonConverter.responseBodyConverter(type, annotations, retrofit); 
    } 

    @Override 
    public Converter<?, RequestBody> requestBodyConverter(Type type, Annotation[] parameterAnnotations, Annotation[] methodAnnotations, Retrofit retrofit) { 
     return new KeyValueBodyConverter<>(gson); 
    } 
} 

In Ihrem Und hier ist unser KeyValueBody

public class KeyValuePairConverter extends retrofit2.Converter.Factory implements Converter { 
    private final Gson gson; 

    public KeyValuePairConverter(Gson gson) { 
     this.gson = gson; 
    } 

    // Taken from retrofit's GsonConverter 
    @Override 
    public Object fromBody(TypedInput body, Type type) throws ConversionException { 
     String charset = MimeUtil.parseCharset(body.mimeType()); 
     InputStreamReader isr = null; 
     try { 
      isr = new InputStreamReader(body.in(), charset); 
      return gson.fromJson(isr, type); 
     } catch (IOException e) { 
      throw new ConversionException(e); 
     } catch (JsonParseException e) { 
      throw new ConversionException(e); 
     } finally { 
      if (isr != null) { 
       try { 
        isr.close(); 
       } catch (IOException ignored) { 
       } 
      } 
     } 
    } 

    @Override 
    public TypedOutput toBody(Object object) { 
     String json = gson.toJson(object); 
     //Log.d("RETROFIT", json); 
     Type type = new TypeToken<Map<String, Object>>() { } .getType(); 

     // this converts any int values to doubles so we are fixing them back in pojoToTypedOutput 
     Map<String, Object> map = gson.fromJson(json, type); 
     String body = pojoToTypedOutput(map, null); 
     // removes the initial ampersand 
     return new TypedString(body.substring(1)); 
    } 

    /** 
    * Converts object to list of query parameters 
    * (works with nested objects) 
    * 
    * @todo 
    * query parameter encoding 
    * 
    * @param map   this is the object map 
    * @param parentKey  this is the parent key for lists/arrays 
    * @return 
    */ 
    public String pojoToTypedOutput(Map<String, Object> map, String parentKey) { 
     StringBuffer sb = new StringBuffer(); 
     if (map != null && map.size() > 0) { 
      for (String key : map.keySet()) { 
       // recursive call for nested objects 
       if (map.get(key).getClass().equals(LinkedTreeMap.class)) { 
        sb.append(pojoToTypedOutput((Map<String, Object>) map.get(key), key)); 
       } else { 
        // parent key for nested objects 
        Object objectValue = map.get(key); 

        // converts any doubles that really could be ints to integers (0.0 to 0) 
        if (objectValue.getClass().equals(Double.class)) { 
         Double doubleValue = (Double) objectValue; 
         if ((doubleValue == Math.floor(doubleValue)) && !Double.isInfinite(doubleValue)) { 
          objectValue = ((Double) objectValue).intValue(); 
         } 
        } 

        if (parentKey != null && parentKey.length() != 0) { 
         sb.append("&").append(key).append("=").append(objectValue); 
        } else { 
         sb.append("&").append(parentKey + "[" + key + "]").append("=").append(objectValue); 
        } 
       } 
      } 
     } 
     return sb.toString(); 
    } 
} 

erweitert Nachrüstungs-Generator hinzufügen .addConverterFactory(RF2_KeyValuePairConverter.create(gson)) und dies wird Ihre Antworten in Schlüssel/Wert Pai konvertieren rs

Verwandte Themen