Esta pergunta pode ter sido feita antes, mas não, não foi definitivamente respondida. Como exatamente postamos JSON inteiro bruto dentro do corpo de uma solicitação de Retrofit?
Veja pergunta semelhante aqui . Ou é esta resposta correta que deve ser codificado em URL e passado como um campo ? Eu realmente espero que não, pois os serviços aos quais estou me conectando esperam apenas JSON bruto no corpo do post. Eles não estão configurados para procurar um campo específico para os dados JSON.
Eu só quero esclarecer isso com os restperts de uma vez por todas. Uma pessoa respondeu para não usar o Retrofit. O outro não tinha certeza da sintaxe. Outro pensa que sim, isso pode ser feito, mas apenas se o formulário for codificado em URL e colocado em um campo (isso não é aceitável no meu caso). Não, não consigo codificar novamente todos os serviços do meu cliente Android. E sim, é muito comum em grandes projetos publicar JSON bruto em vez de passar o conteúdo JSON como valores de propriedade do campo. Vamos acertar e seguir em frente. Alguém pode apontar para a documentação ou exemplo que mostra como isso é feito? Ou forneça uma razão válida pela qual isso não pode / não deve ser feito.
ATUALIZAÇÃO: Uma coisa que posso dizer com 100% de certeza. Você pode fazer isso no Google Volley. Está embutido. Podemos fazer isso no Retrofit?
RequestBody
assim ->RequestBody body = RequestBody.create(MediaType.parse("text/plain"), text);
para obter respostas detalhadas futurestud.io/tutorials/…Respostas:
A
@Body
anotação define um único corpo de solicitação.Como o Retrofit usa o Gson por padrão, as
FooRequest
instâncias serão serializadas como JSON como o único corpo da solicitação.Ligando com:
Produzirá o seguinte corpo:
Os documentos do Gson têm muito mais informações sobre como a serialização de objetos funciona.
Agora, se você realmente deseja enviar o JSON "bruto" como o seu próprio corpo (mas use o Gson para isso!), Ainda poderá usar
TypedInput
:TypedInput é definido como "Dados binários com um tipo mime associado". Há duas maneiras de enviar facilmente dados brutos com a declaração acima:
Use TypedByteArray para enviar bytes não processados e o tipo mime JSON:
Subclasse TypedString para criar uma
TypedJsonString
classe:E, em seguida, use uma instância dessa classe semelhante ao nº 1.
fonte
TypedString
desde que foi removido?RequestBody
para criar um corpo bruto.java.lang.IllegalArgumentException: Unable to create @Body converter for class MatchAPIRequestBody (parameter #1)
Em vez de classes, também podemos usar diretamente o
HashMap<String, Object>
para enviar parâmetros do corpo, por exemplofonte
IllegalArgumentException: Unable to create @Body converter for java.util.HashMap<java.lang.String, java.lang.Object>
com Moshi. Acho Gson é necessária para que isso funcioneSim, eu sei que é tarde, mas alguém provavelmente se beneficiaria com isso.
Usando o Retrofit2:
Encontrei esse problema na noite passada ao migrar do Volley para o Retrofit2 (e, como afirma o OP, isso foi incorporado ao Volley
JsonObjectRequest
), e embora a resposta de Jake seja a correta para o Retrofit1.9 , o Retrofit2 não possuiTypedString
.Meu caso exigia o envio de um
Map<String,Object>
que pudesse conter alguns valores nulos, convertido em um JSONObject (que não voa com@FieldMap
, nem caracteres especiais, alguns são convertidos), portanto, seguindo a dica @bnorms, e conforme declarado por Square :Portanto, esta é uma opção usando
RequestBody
eResponseBody
:Na sua interface, use
@Body
comRequestBody
No seu ponto de chamada, crie um
RequestBody
, indicando seu MediaType, e usando JSONObject para converter seu mapa no formato adequado:Espero que isso ajude alguém!
Uma versão elegante do Kotlin acima, para permitir abstrair os parâmetros da conversão JSON no restante do código do aplicativo:
fonte
JsonObjectRequest
, tudo o que você precisa fazer é isso. Boa resposta.post a null value
a acessar uma propriedade no requestBody que, de outra forma, estava sendo ignorada.jsonParams.put("code", some_code);
na terceira linha?No Retrofit2 , quando você deseja enviar seus parâmetros em bruto, deve usar escalares .
adicione primeiro no seu gradle:
Sua interface
Atividade
fonte
GsonConverterFactory
, o.toString()
não é necessário. Você pode declararCall<User> getUser(@Body JsonObject body);
usando emJsonObject
vez deJSONObject
e passar oparamObject
diretamente. Funcionará muito bem.Usando
JsonObject
é da maneira que é:Crie sua interface assim:
Faça o JsonObject de acordo com a estrutura jsons.
Ligue para o serviço:
E é isso! Na minha opinião pessoal, é muito melhor do que fazer pojos e trabalhar com a bagunça da classe. Isso é muito mais limpo.
fonte
Eu particularmente gosto da sugestão de Jake da
TypedString
subclasse acima . Você pode realmente criar uma variedade de subclasses com base nos tipos de dados do POST que planeja enviar, cada um com seu próprio conjunto personalizado de ajustes consistentes.Você também tem a opção de adicionar uma anotação de cabeçalho aos métodos JSON POST na sua API Retrofit…
... mas usar uma subclasse é mais obviamente auto-documentado.
fonte
1) Adicionar dependências
2) faça a classe Api Handler
3) criar classes de bean a partir do esquema Json 2 pojo
http://www.jsonschema2pojo.org/
4) faça a interface para a api chamando
5) faça o JsonObject para passar para o corpo como parâmetro
6) Ligue para a Api assim
fonte
Descobri que quando você usa um objeto composto como
@Body
parâmetro, ele não funciona bem com o RetrofitGSONConverter
(sob a suposição de que você esteja usando isso). Você precisa usarJsonObject
e nãoJSONObject
ao trabalhar com isso, ele adicionaNameValueParams
sem ser detalhado - só é possível ver que se você adicionar outra dependência do interceptador de log e outras travessuras.Então, o que eu achei a melhor abordagem para resolver isso está usando
RequestBody
. Você transforma seu objetoRequestBody
com uma simples chamada de API e o inicia. No meu caso, estou convertendo um mapa:e esta é a chamada:
fonte
Adicione ScalarsConverterFactory à atualização:
em gradle:
seu retrofit:
altere o parâmetro @Body da interface de chamada para String, não se esqueça de adicionar
@Headers("Content-Type: application/json")
:agora você pode postar json bruto.
fonte
Você pode usar o hashmap se não desejar criar a classe pojo para cada chamada da API.
E então envie assim
fonte
Depois de tanto esforço, descobriu que a diferença básica é que você precisa enviar o parâmetro em
JsonObject
vez deJSONObject
como.fonte
use o seguinte para enviar json
e passe para url
fonte
Com base na resposta principal, tenho uma solução para não precisar criar POJOs para cada solicitação.
Exemplo, quero postar este JSON.
então, crio uma classe comum como esta:
Finalmente, quando eu preciso de um json
A solicitação marcada como anotação
@Body
pode passar para Retrofit.fonte
Se você não deseja criar classes extras ou usar,
JSONObject
pode usar aHashMap
.Interface de modernização:
Ligar:
fonte
Itens necessários para enviar json bruto no Retrofit.
1) Certifique-se de adicionar o cabeçalho a seguir e remover qualquer outro cabeçalho duplicado. Visto que, na documentação oficial da Retrofit, eles mencionam especificamente
2) a. Se você estiver usando uma fábrica de conversores, poderá passar seu json como uma String, JSONObject, JsonObject e até um POJO. Também verifiquei,
ScalarConverterFactory
não é necessário apenasGsonConverterFactory
fazer o trabalho.2) b. Se você NÃO estiver usando nenhuma fábrica de conversores, DEVE usar o RequestBody do okhttp3 como a documentação do Retrofit diz:
3) Sucesso !!
fonte
É isso que funciona para a versão atual do
retrofit
2.6.2 ,Primeiro, precisamos adicionar um conversor de escalares à lista de nossas dependências Gradle, que cuidaria da conversão de objetos java.lang.String em corpos de solicitação de texto / sem formatação,
Então, precisamos passar uma fábrica de conversores para o nosso construtor Retrofit. Mais tarde, informará à Retrofit como converter o parâmetro @Body passado para o serviço.
Em seguida, atualize o serviço com um parâmetro de corpo String.
Em seguida, crie o corpo JSON
Ligue para o seu serviço
fonte
✅✅✅✅✅✅✅✅✅✅✅✅ Solução de Trabalho ✅✅✅✅✅✅✅✅✅✅✅✅
Ao criar
OkHttpClient
isso, será usado para o Retrofit.adicione um interceptor como este.
Agora URL e solicitar corpo todas as suas Retrofit de chamada será registrado no
Logcat
. Filtre por"gsonrequest"
fonte
Eu tentei o seguinte: Quando você estiver criando sua instância de Retrofit, adicione esta fábrica de conversores ao construtor de retrofit:
fonte
Resolvi o meu problema com base na resposta do TommySM (veja anterior). Mas eu não precisava fazer login, usei o Retrofit2 para testar a API https GraphQL da seguinte forma:
Definiu minha classe BaseResponse com a ajuda de anotações json (import jackson.annotation.JsonProperty).
Definiu o procedimento de chamada na interface:
Chamado apicall no corpo do teste: Crie uma variável do tipo MyRequest (por exemplo "myLittleRequest").
fonte
Para mais clareza nas respostas fornecidas aqui, é assim que você pode usar as funções de extensão. Isso é apenas se você estiver usando o Kotlin
Se você estiver usando
com.squareup.okhttp3:okhttp:4.0.1
os métodos mais antigos de criação de objetos do MediaType e RequestBody , foi preterido e não pode ser usado no Kotlin .Se você deseja usar as funções de extensão para obter um objeto MediaType e um objeto ResponseBody de suas seqüências, primeiro adicione as seguintes linhas à classe na qual você espera usá-las.
Agora você pode obter diretamente um objeto do MediaType dessa maneira
Para obter um objeto RequestBody, primeiro converta o JSONObject que você deseja enviar para uma string dessa maneira. Você precisa passar o objeto mediaType para ele.
fonte
Eu queria comparar a velocidade do vôlei e o retrofit para enviar e receber dados que escrevi abaixo do código (para parte do retrofit)
primeira dependência:
Então faça a interface:
e uma função para definir parâmetros para postar dados no servidor (In MainActivity):
E eu encontrei o Retrofit mais rápido que o vôlei no meu caso.
fonte