这个问题可能以前曾被问过,但没有得到明确答复。如何在 Retrofit 请求的主体内发布原始整个 JSON?
看到类似的问题这里。或者这个答案是否正确必须是表单 url 编码并作为字段传递?我真的希望不会,因为我所连接的服务只是期待帖子正文中的原始 JSON。它们未设置为查找 JSON 数据的特定字段。
我只想一劳永逸地与其他人一起澄清这一点。一个人回答不使用 Retrofit。另一个不确定语法。另一个人认为可以这样做,但只有当它的形式 url-encoded 并放在一个字段中时(在我的情况下这是不可接受的)。不,我不能 re-code 我的 Android 客户端的所有服务。是的,在主要项目中发布原始 JSON 而不是将 JSON 内容作为字段属性值传递是很常见的。让我们做对了,继续前进吧。有人可以指向显示如何完成此操作的文档或示例吗?或者提供一个有效的原因 can/should 没有完成。
更新:我可以 100%确定地说一件事。你可以在谷歌的排球中做到这一点。它是内置的。我们可以在 Retrofit 中做到这一点吗?
16 回答
@Body注释定义单个请求主体。
由于 Retrofit 默认使用 Gson,因此
FooRequest
实例将序列化为 JSON 作为请求的唯一主体。致电:
将产生以下身体:
Gson 博士在对象序列化的工作原理方面有很多。
现在,如果你真的想要自己发送“原始”JSON 作为身体(但请使用 Gson!)你仍然可以使用
TypedInput
:TypedInput定义为“具有关联 mime 类型的二进制数据”。使用上述声明可以通过两种方式轻松发送原始数据:
TypedJsonString
类:然后使用类似#1 的那个类的实例。
我们也可以直接使用
HashMap<String, Object>
来发送 body 参数,而不是类是的,我知道现在已经很晚了,但有人可能会从中受益。
使用 Retrofit2:
我昨晚遇到了这个问题,从 Volley 迁移到了 Retrofit2(并且作为 OP 状态,这是使用
JsonObjectRequest
直接进入 Volley),尽管Jake 的答案是 Retrofit1.9的正确答案,但 Retrofit2 没有TypedString
。我的情况需要发送一个
Map<String,Object>
,它可能包含一些空值,转换为 JSONObject(不会与@FieldMap
一起飞行,也不会转换为特殊字符,有些转换),所以 following @bnorms hint,并且如广场所述:该对象也将使用 Retrofit 实例上指定的转换器进行转换。如果未添加转换器,则只能使用 RequestBody。
所以这是一个使用
RequestBody
和ResponseBody
的选项:在你的界面中使用
@Body
和RequestBody
在你的调用点创建一个
RequestBody
,声明它是 MediaType,并使用 JSONObject 将你的 Map 转换为正确的格式:希望这有助于任何人!
上面的优雅 Kotlin 版本,允许从其他应用程序代码中的 JSON 转换中抽象出参数:
在Retrofit2中,当您想要以 raw 格式发送参数时,必须使用 Scalars。
首先在你的 gradle 中添加:
您的界面
活动
使用
JsonObject
是这样的:那就是它!在我个人看来,它比制作 pojos 和处理课堂混乱要好得多。这更清洁了。
我特别喜欢杰克对
TypedString
子类以上的建议。您确实可以根据您计划推送的各种 POST 数据创建各种子类,每个子类都有自己的一组自定义调整。您还可以选择在 Retrofit API 中的 JSON POST 方法中添加标题注释...
...但是使用子类更明显是 self-documenting。
1)Add 依赖 -
来自 Json schema 2 pojo 的 3)make bean 类
http://www.jsonschema2pojo.org/
来自 api 呼叫的 4)make 接口
5)make JsonObject 用于作为参数传入 body
我发现当你使用复合对象作为
@Body
params 时,它对于 Retrofit 的GSONConverter
(假设你正在使用它)不能很好地工作。使用JsonObject
时,你必须使用JsonObject
而不是JSONObject
,它添加NameValueParams
而不是冗长 - 你只能看到如果你添加另一个日志拦截器和其他恶作剧的依赖项。所以我发现解决这个问题的最佳方法是使用
RequestBody
。您可以通过简单的 api 调用将对象转换为RequestBody
并启动它。在我的情况下,我正在转换地图:这就是电话:
添加 ScalarsConverterFactory 进行改造:
在 gradle 中:
你的改造:
将您的调用 interface @Body parameter 更改为 String,不要忘记添加
@Headers("Content-Type: application/json")
:现在你可以发布原始的 json。
经过这么多的努力,发现基本的区别是你需要发送
JsonObject
而不是JSONObject
作为参数。使用以下来发送 json
并将其传递给网址
根据最佳答案,我有一个解决方案,不必为每个请求制作 POJO。
例如,我想发布这个 JSON。
然后,我创建一个这样的公共类:
最后,当我需要一个 json
请求标记为注释
@Body
然后可以传递给 Retrofit。如果您不想创建额外的类或使用
JSONObject
,您可以使用HashMap
。改造界面:
呼叫:
我试过这个:在创建 Retrofit 实例时,将此转换器工厂添加到改造构建器:
为了更清楚地说明这里给出的答案,您可以使用扩展功能。 这只适用于您使用 Kotlin
如果您使用的是
com.squareup.okhttp3:okhttp:4.0.1
,那么创建MediaType和RequestBody对象的旧方法已被弃用,不能在 Kotlin 中使用。如果要使用扩展函数从字符串中获取MediaType对象和ResponseBody对象,请首先将以下行添加到您希望使用它们的类中。
您现在可以通过这种方式直接获取MediaType的对象
要获取RequestBody的对象,首先将要发送的 JSONObject 转换为字符串。您必须将 mediaType 对象传递给它。
如果您不想为每个 API 调用创建 pojo 类,则可以使用 hashmap。
然后像这样发送