To pytanie mogło zostać zadane wcześniej, ale nie, na które nie udzielono ostatecznej odpowiedzi. Jak dokładnie jeden post surowego całego JSON znajduje się w treści wniosku o modernizację?
Zobacz podobne pytanie tutaj . Czy ta odpowiedź jest poprawna, że musi być zakodowana z adresu URL i przekazana jako pole ? Naprawdę mam nadzieję, że nie, ponieważ usługi, z którymi się łączę, po prostu oczekują surowego JSON w treści postu. Nie są skonfigurowane do wyszukiwania określonego pola dla danych JSON.
Chcę tylko wyjaśnić to z restperts raz na zawsze. Jedna osoba odpowiedziała, aby nie używać Modernizacji. Drugi nie był pewien składni. Inny uważa, że tak, można to zrobić, ale tylko wtedy, gdy jego forma jest zakodowana w url i umieszczona w polu (w moim przypadku jest to nie do przyjęcia). Nie, nie mogę ponownie kodować wszystkich usług mojego klienta Android. I tak, w dużych projektach bardzo często publikuje się surowy JSON zamiast przekazywać zawartość JSON jako wartości właściwości pola. Zróbmy to dobrze i przejdźmy dalej. Czy ktoś może wskazać dokumentację lub przykład, który pokazuje, jak to się robi? Lub podaj prawidłowy powód, dla którego nie można tego zrobić.
AKTUALIZACJA: Jedno mogę powiedzieć ze 100% pewnością. Możesz to zrobić w Google Volley. Jest wbudowany. Czy możemy to zrobić w ramach modernizacji?
RequestBody
tym w ten sposób ->RequestBody body = RequestBody.create(MediaType.parse("text/plain"), text);
szczegółowa odpowiedź futurestud.io/tutorials/...Odpowiedzi:
@Body
Adnotacja wyznacza jeden organ żądania.Ponieważ Retrofit domyślnie korzysta z Gson,
FooRequest
instancje będą serializowane jako JSON jako jedyna treść żądania.Dzwonię z:
Przyniesie następujące ciało:
Dokumenty Gson mają znacznie więcej informacji na temat serializacji obiektów.
Teraz, jeśli naprawdę chcesz sam wysłać „surowe” JSON jako ciało (ale w tym celu użyj Gsona!), Nadal możesz używać
TypedInput
:TypedInput jest zdefiniowany jako „Dane binarne z powiązanym typem MIME”. Istnieją dwa sposoby łatwego wysyłania surowych danych z powyższą deklaracją:
Użyj TypedByteArray, aby wysłać surowe bajty i typ MIME JSON:
Podklasa TypedString, aby utworzyć
TypedJsonString
klasę:A następnie użyj instancji tej klasy podobnej do # 1.
źródło
TypedString
skoro została usunięta?RequestBody
do utworzenia surowego obiektu.java.lang.IllegalArgumentException: Unable to create @Body converter for class MatchAPIRequestBody (parameter #1)
Zamiast klas możemy również bezpośrednio użyć
HashMap<String, Object>
na przykład parametrów wysyłania ciałaźródło
IllegalArgumentException: Unable to create @Body converter for java.util.HashMap<java.lang.String, java.lang.Object>
z Moshi. Myślę, że Gson jest do tego potrzebnyTak, wiem, że jest późno, ale ktoś prawdopodobnie skorzystałby na tym.
Korzystanie z Retrofit2:
Natknąłem się na ten problem podczas migracji z Volley do Retrofit2 (i jak twierdzi OP, został on wbudowany w Volley z
JsonObjectRequest
) i chociaż odpowiedź Jake'a jest poprawna dla Retrofit1.9 , Retrofit2 nie maTypedString
.Mój przypadek wymagał wysłania wartości,
Map<String,Object>
która mogłaby zawierać pewne wartości null, przekonwertowane na obiekt JSONObject (który nie będzie latał@FieldMap
, nie zostaną też przekonwertowane znaki specjalne, niektóre zostaną przekonwertowane), więc zgodnie ze wskazówkami @bnorms i zgodnie z twierdzeniem Square :Jest to więc opcja przy użyciu
RequestBody
iResponseBody
:W interfejsie używaj
@Body
zRequestBody
W punkcie wywoławczym utwórz
RequestBody
, podając MediaType i używając JSONObject do konwersji mapy do odpowiedniego formatu:Mam nadzieję, że to pomoże każdemu!
Elegancka wersja powyższego Kotlina, aby umożliwić wyodrębnienie parametrów z konwersji JSON w pozostałej części kodu aplikacji:
źródło
JsonObjectRequest
, wszystko, co musisz zrobić, to zrobić. Dobra odpowiedź.post a null value
do właściwości w requestBody, która w przeciwnym razie była ignorowana.jsonParams.put("code", some_code);
w trzeciej linii?W Retrofit2 , jeśli chcesz przesłać swoje parametry w stanie surowym, musisz użyć skalarów .
najpierw dodaj to do swojej klasy:
Twój interfejs
Czynność
źródło
GsonConverterFactory
The.toString()
nie jest konieczne. Możesz zadeklarowaćCall<User> getUser(@Body JsonObject body);
użycieJsonObject
zamiastJSONObject
i przekazaćparamObject
bezpośrednio. Będzie dobrze działać.Używanie
JsonObject
jest takie, jak to jest:Utwórz interfejs w następujący sposób:
Wykonaj JsonObject zgodnie ze strukturą jsons.
Zadzwoń do serwisu:
I to jest to! Moim osobistym zdaniem jest to o wiele lepsze niż tworzenie koncepcji i praca z klasowym bałaganem. To jest o wiele czystsze.
źródło
Szczególnie podoba mi się sugestia Jake'a z
TypedString
podklasy powyżej . Rzeczywiście możesz stworzyć wiele podklas w oparciu o rodzaje danych POST, które planujesz zwiększyć, każda z własnym niestandardowym zestawem spójnych poprawek.Masz również opcję dodania adnotacji nagłówka do metod JSON POST w interfejsie API Retrofit…
… Ale użycie podklasy jest bardziej oczywiste.
źródło
1) Dodaj zależności
2) uczynić klasę Api Handler
3) twórz klasy fasoli ze schematu Jsona 2 pojo
http://www.jsonschema2pojo.org/
4) wykonaj interfejs do wywoływania interfejsu API
5) ustaw JsonObject do przekazania do ciała jako parametr
6) Zadzwoń do API w ten sposób
źródło
Odkryłem, że kiedy używasz obiektu złożonego jako
@Body
params, nie może on dobrze działać z RetrofitGSONConverter
(przy założeniu, że go używasz). Musisz używać,JsonObject
a nieJSONObject
podczas pracy z tym, dodaje toNameValueParams
bez mówienia o tym - możesz to zobaczyć tylko wtedy, gdy dodasz inną zależność rejestrowania przechwytywacza i innych shenaniganów.Więc to, co znalazłem najlepsze podejście do rozwiązania tego problemu, to wykorzystanie
RequestBody
. Obróć swój obiektRequestBody
za pomocą prostego wywołania interfejsu API i uruchom go. W moim przypadku przekształcam mapę:i to jest wezwanie:
źródło
Dodaj ScalarsConverterFactory do modernizacji:
w stopniach:
Twoja modernizacja:
zmień parametr @Body interfejsu wywołania na String, nie zapomnij dodać
@Headers("Content-Type: application/json")
:teraz możesz pisać surowego Jsona.
źródło
Możesz użyć hashmap, jeśli nie chcesz tworzyć klasy pojo dla każdego wywołania API.
A potem wyślij tak
źródło
Po tylu wysiłkach okazało się, że podstawową różnicą jest przesłanie parametru
JsonObject
zamiastJSONObject
jako parametru.źródło
użyj następującego, aby wysłać json
i przekaż to na adres URL
źródło
W oparciu o najwyższą odpowiedź mam rozwiązanie, aby nie musieć tworzyć POJO dla każdego żądania.
Przykład, chcę opublikować ten JSON.
następnie tworzę wspólną klasę taką jak ta:
Wreszcie, kiedy potrzebuję jsona
Żądanie oznaczone adnotacją
@Body
może następnie przejść do modernizacji.źródło
Jeśli nie chcesz tworzyć dodatkowych klas ani używać
JSONObject
, możesz użyćHashMap
.Interfejs modernizacji:
Połączenie:
źródło
Rzeczy wymagane do wysłania surowego Jsona w ramach modernizacji.
1) Pamiętaj, aby dodać następujący nagłówek i usunąć wszelkie inne zduplikowane nagłówki. Ponieważ w oficjalnej dokumentacji Retrofit wyraźnie wspominają:
2) a. Jeśli używasz fabryki konwerterów, możesz przekazać json jako String, JSONObject, JsonObject, a nawet POJO. Sprawdziłem również, że posiadanie
ScalarConverterFactory
nie jest konieczne tylkoGsonConverterFactory
wykonuje pracę.2) b. Jeśli NIE korzystasz z żadnej fabryki konwerterów, MUSISZ użyć RequestBody okhttp3, ponieważ dokumentacja Retrofit mówi:
3) Sukces !!
źródło
To działa dla mnie w bieżącej wersji
retrofit
2.6.2 ,Przede wszystkim musimy dodać konwerter skalarów do listy naszych zależności Gradle, który zająłby się konwertowaniem obiektów java.lang.String na ciała tekstowe / zwykłe żądania,
Następnie musimy przekazać fabrykę konwerterów do naszego konstruktora modernizacji. Później powie Retrofit, jak przekonwertować parametr @Body przekazany do usługi.
Następnie usługa modernizacji z parametrem Body String.
Następnie utwórz ciało JSON
Zadzwoń do serwisu
źródło
✅✅✅✅✅✅✅✅✅✅✅✅ Działające rozwiązanie ✅✅✅✅✅✅✅✅✅✅✅✅
Podczas tworzenia
OkHttpClient
zostanie użyty do modernizacji.dodaj taki przechwytywacz.
Teraz URL i treści żądania spełnić każde modernizacyjny wywołania będą rejestrowane w
Logcat
. Filtruj według"gsonrequest"
źródło
Próbowałem tego: podczas tworzenia instancji Retrofit dodaj tę fabrykę konwerterów do konstruktora modernizacji:
źródło
Rozwiązałem mój problem na podstawie odpowiedzi TommySM (patrz poprzedni). Ale nie musiałem się logować, użyłem Retrofit2 do testowania API https GraphQL w następujący sposób:
Zdefiniowałem moją klasę BaseResponse za pomocą adnotacji json (import jackson.annotation.JsonProperty).
Zdefiniowano procedurę wywołania w interfejsie:
W treści testu nazywany apicall: utwórz zmienną typu MyRequest (na przykład „myLittleRequest”).
źródło
Aby uzyskać większą przejrzystość podanych tutaj odpowiedzi, możesz skorzystać z funkcji rozszerzenia. Jest to możliwe tylko w przypadku korzystania z Kotlin
Jeśli korzystasz
com.squareup.okhttp3:okhttp:4.0.1
ze starszych metod tworzenia obiektów MediaType i RequestBody, są one przestarzałe i nie można ich używać w Kotlin .Jeśli chcesz użyć funkcji rozszerzenia, aby uzyskać obiekt MediaType i obiekt ResponseBody ze swoich ciągów, najpierw dodaj następujące wiersze do klasy, w której spodziewasz się ich użyć.
W ten sposób możesz teraz bezpośrednio uzyskać obiekt MediaType
Aby uzyskać obiekt RequestBody, najpierw przekonwertuj obiekt JSONObject, który chcesz wysłać w ten sposób na ciąg. Musisz przekazać do niego obiekt mediaType.
źródło
Chciałem porównać prędkość siatkówki i modernizacji do wysyłania i odbierania danych, które napisałem poniżej kodu (dla części modernizacyjnej)
pierwsza zależność:
Następnie interfejs:
oraz funkcja do ustawiania parametrów wysyłania danych do serwera (w MainActivity):
W moim przypadku odnalazłem Retrofit szybciej niż siatkówkę.
źródło