PHP API 不能与改造/gson 结合使用
Posted
技术标签:
【中文标题】PHP API 不能与改造/gson 结合使用【英文标题】:PHP API not working in conjuntion with retrofit/gson 【发布时间】:2021-04-28 00:44:45 【问题描述】:我无法让我的 REST API 使用改造/gson 处理来自我的 android 应用程序的 POST 请求。支持 REST API 的功能是接受非常基本的 JSON 解码,在其上运行一系列 SQL 查询,然后将格式化的 JSON 数据返回给应用程序。
我知道问题不在于 API 逻辑,当我将传入的 JSON 数据硬编码或将 JSON 响应硬编码到 php 中时,API 工作正常。当我需要使用来自应用程序的 POST 请求传递 JSON 时,问题就开始了。我总是得到以下例外:FATAL EXCEPTION: DefaultDispatcher-worker-1
或 FATAL EXCEPTION: DefaultDispatcher-worker-2
传入的 JSON 来自应用程序。
我尝试了 3 种接收传入 JSON 的方法。第一个是使用$jsonobj = http_get_request_body();
函数,第二个是$jsonobj = file_get_contents('php://input');
,第三个是 $jsonobj = $_POST['code'];
,最后一个很有趣。我不知道['here']
中的内容是什么,或者名称是什么,所以我可以使用它。我已经尝试在此处更改 ['text']
几次,但没有成功。
在我们继续之前,这里是我的 PHP 脚本的概述。
//database config here.
if($_SERVER["REQUEST_METHOD"] == "POST")
//method of reciving JSON here.
$obj = json_decode($jsonobj);
//SQL logic here.
echo json_encode($return);
如果不是 JSON 接收器,这将有效。
还有一个很好的机会,我什至根本不发送 JSON,更不用说有效的 JSON。我知道有记录出站 JSON 的方法,但对于我的生活,我无法让它们工作。所以在这里我将发布一些我的android代码。
我的 API 接口
interface API
@POST("posttest.php")
suspend fun postit(@Body post: String): Phone
我在这种情况下使用上述接口
val api = Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(API::class.java)
GlobalScope.launch(Dispatchers.IO)
val response = api.postit(test)
try
//logic
catch (e: Exception)
//error handling
我想从房间数据库中提取 JSON,但我还没有这样做,所以我只对 JSON 进行了硬编码;它看起来像这样。
private var test = "[\"text1\", \"text2\", \"text3\"]"
感谢您的宝贵时间。
【问题讨论】:
你可以尝试在没有 json_decode 和 SQL 逻辑的情况下返回 $jsonobj 并将其登录到 android 以检查你发送的内容。 好主意,我该怎么做? 我的答案在下面... 【参考方案1】:以下是仅用于与 API 建立应用程序连接的代码。您将根据自己的需求调整其他所有内容(改造请求、响应、json 编码)
在 Android 应用中关注日志
我强烈建议您不要在没有数据验证的情况下查询数据库并使用 PDO
最好使用一些 php 框架的 api,如 Slim、Laravel、Lumen
您可以使用最常用的类型之一发布请求:
application/x-www-form-urlencoded = 参数编码 application/json = 发送 json 数据 //用于你的情况 multipart/form-data = 图片等文件你的 PHP 脚本应该是这样的
if($_SERVER["REQUEST_METHOD"] == "POST")
//TODO this is only example to get and return json data
$jsonobj = file_get_contents('php://input');
$json = json_decode($jsonobj);
$response = array(
"raw" => $jsonobj,
"json" => $json
);
echo json_encode($response);
else
//Send a 405 Method Not Allowed
http_response_code(405);
exit;
接口接口
interface API
@POST("posttest.php")
suspend fun postIt(@Body requestBody: RequestBody): Response<ResponseBody>
和主要的
val api = Retrofit.Builder()
.baseUrl(BASE_URL)
//.addConverterFactory(GsonConverterFactory.create())
.build()
.create(API::class.java);
val test = "[\"text1\", \"text2\", \"text3\"]"; //hardcoded by you
val requestBody = test.toRequestBody("application/json".toMediaTypeOrNull())
GlobalScope.launch(Dispatchers.IO)
val response = api.postIt(requestBody)
//withContext(Dispatchers.Main)
try
if (response.isSuccessful)
Log.i("RESPONSE", "DATA: " + response.body()?.string());
else
Log.i("RESPONSE", "ERROR: " + response.errorBody()?.string());
Log.i("RESPONSE", "RAW: " + response.raw());
catch (e: Exception)
e.printStackTrace();
//error handling
//
【讨论】:
感谢您在此回复中投入的时间和精力。我根据您的规范制作了一个新的应用程序和 PHP 脚本来测试 API,我在 logcat 中获得了这两项。apitest I/RESPONSE: DATA: "raw":"[\"text1\", \"text2\", \"text3\"]","json":["text1","text2","text3"]
和 apitest I/RESPONSE: RAW: Responseprotocol=http/1.1, code=200, message=OK, url=http://10.0.2.2/posttest2.php
。我忽略指定这是否也出现在日志 cat `com.google.gson.stream.MalformedJsonException: Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 1 path $`
我刚刚准备好你的代码来发送你的硬编码 json,然后是 php 脚本来检索它,解码它并以原始和 json 格式返回给应用程序......我不知道是什么您想发送并返回到应用程序..您必须根据需要调整改造...尝试发送其他内容,插入数据库并返回您想要的内容
这似乎是一个奇怪的问题,但是哪个变量将发送回 PHP 脚本的 JSON 发回?因为如果 JSON 包含所有额外的内容,那么脚本无法正常工作是有意义的
在这种情况下,您从 android 发送的 json 将以原始和 json 格式返回给您,并带有 echo json_encode ($response);如果我很好地理解了这个问题...... $json 变量包含解码后的 json,你可以用它做任何你想做的事情【参考方案2】:
事实证明问题出在我的 PHP API code
非常感谢用户:404438 @kylexy1357 给了我日志记录代码,所以我可以看到发生了什么
他的code
val gson = GsonBuilder()
.setLenient()
.create()
val builder = OkHttpClient().newBuilder()
builder.readTimeout(120, TimeUnit.SECONDS)
builder.connectTimeout(30, TimeUnit.SECONDS)
if (BuildConfig.DEBUG)
val interceptor = HttpLoggingInterceptor()
interceptor.level = HttpLoggingInterceptor.Level.BASIC
builder.addInterceptor(interceptor)
val client = builder.build()
val retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.client(client)
.build()
【讨论】:
以上是关于PHP API 不能与改造/gson 结合使用的主要内容,如果未能解决你的问题,请参考以下文章