来自swift的JSON请求在php中显示空数组
Posted
技术标签:
【中文标题】来自swift的JSON请求在php中显示空数组【英文标题】:JSON request from swift showing empty array in php 【发布时间】:2019-12-13 20:07:17 【问题描述】:我正在尝试从我的 swift 应用程序向 php 服务器发出请求。由于某种原因,php 将一个空数组显示为 $_REQUEST 变量。我已经查看了堆栈溢出并实现了我能找到的所有可能有帮助的东西,但仍然在 php.ini 中得到一个空数组。这是相关的swift代码...
func connect(_ pin: String, completion: @escaping(Result<ConnectResponse?, Error>) -> ())
let params: [String : Any] = [
"mobile_pin_connect": pin,
"device_info": UIDevice().model,
"additional_info": UIDevice().systemVersion
]
doRequest(params: params) (data) in
if let data = data
do
let res = try JSONDecoder().decode(Dictionary<String, String>.self, from: data)
completion(.success(
ConnectResponse(success: (res["success"] == "true"), connect_id: res["connect_id"] ?? nil, error: res["error"] ?? nil)))
catch
completion(.failure(error))
else
print("in else block")
fileprivate func doRequest(params: [String: Any], completion: @escaping (Data?) -> ())
let body = createJsonBody(params)!
self.request.httpBody = body
print("Sending request with thw following variables")
print(String(data: body, encoding: .utf8)!)
print(String(data: self.request.httpBody!, encoding: .utf8))
URLSession.shared.dataTask(with: self.request) (data, response, error) in
if let error = error
print("Error in request: \(error)")
completion(nil)
let stringResult = String(data: data!, encoding: .utf8)!
let properResult = String(stringResult.map
$0 == "." ? "=" : $0
)
let decodedData = Data(base64Encoded: properResult)
completion(decodedData)
.resume()
fileprivate func createJsonBody(_ params: [String: Any]) -> Data?
do
let jsonData = try JSONSerialization.data(withJSONObject: params)
let body = Data(jsonData).base64EncodedData()
return body
catch
print("Unable to create json body: " + error.localizedDescription, error)
return nil
将请求发送到服务器,请求的设置在静态变量设置中...
private static var sharedConnector: ApiConnector =
let url = URL(string: "https://mywebsiteURLhere.com/api/mobile/challenge")
var request = URLRequest(url: url!)
request.httpMethod = "POST"
request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
let connector = ApiConnector(request)
return connector
()
所以我为 application/json 设置了正确的标头值,我设置了要发布的请求方法,我正在对 json 数据进行 base64 编码,并且在 PHP 中我设置了 php://input...
$rawRequest = file_get_contents("php://input");
并将 $_REQUEST 变量转储到错误日志中,但我总是得到数组\n(\n)\n 它只是显示一个空数组 我什至做到了
error_log("Raw request from index.php");
error_log(print_r($rawRequest, true));
它记录了一个完全空的行。 从我在网上看到的所有内容中,我无法弄清楚为什么 PHP 在请求中什么也没得到,我正在迅速正确地执行请求。非常感谢任何帮助。谢谢
【问题讨论】:
error_log(print_r($rawRequest, true));
不等于 error_log(print_r($_REQUEST));
首先,即使您成功发送了 JSON,$_REQUEST
也会为空。无论如何,小代码片段无助于解决您的问题。显示 PHP 和 Swift 的可构建和可执行代码。问题可能隐藏在隐藏的部分。
【参考方案1】:
根据您的 Swift 代码,能否请您替换以下方法。
fileprivate func createJsonBody(_ params: [String: Any]) -> Data?
do
let jsonData = try JSONSerialization.data(withJSONObject: params)
let body = Data(jsonData)
return body
catch
print("Unable to create json body: " + error.localizedDescription, error)
return nil
您需要将这一行 let body = Data(jsonData)
替换为
let body = Data(jsonData).base64EncodedData()
【讨论】:
【参考方案2】:没有看到你的 PHP 代码,很难确定整个画面。但是,无论您执行什么步骤通过客户端 (Swift) 对数据进行编码,您都必须反转才能成功解码服务器上的消息。
例如,如果您准备并发送来自客户的请求,如下所示。
客户:
-
JSON 编码数据
base-64 编码
发送数据
您的服务器必须反转步骤才能成功解码数据。
服务器:
-
接收数据
base-64 解码数据
JSON 解码数据
除非您的服务器需要,否则我会删除 base-64 编码步骤,因为它只会使您的编码/解码过程复杂化。
我创建了一个工作示例:https://github.com/stuartcarnie/***/tree/master/q59329179
克隆它或在你自己的项目中拉下特定代码。
要测试,打开终端并运行 php 服务器:
$ cd q59329179/php
$ php -S localhost:8080 router.php
PHP 7.3.9 Development Server started at Thu Dec 19 10:47:58 2019
Listening on http://localhost:8080
Document root is /Users/stuartcarnie/projects/***/q59329179/php
Press Ctrl-C to quit.
在另一个终端会话中测试它是否适用于 curl:
$ curl -XPOST localhost:8080 --data-binary '"string": "foo", "number": 5'
请注意,您应该在 php 会话中看到输出:
[Thu Dec 19 11:33:43 2019] Array
(
[string] => foo
[number] => 5
)
运行 Swift 测试:
$ cd q59329179/swift
$ swift run request
再次注意,php会话中的解码输出:
[Thu Dec 19 11:20:49 2019] Array
(
[string] => string value
[number] => 12345
[bool] =>
)
【讨论】:
【参考方案3】:您的请求可能没有通过 POST 结构到达,而是保存在请求正文中。
尝试将其作为您的第一个 PHP 操作运行:
$raw = file_get_contents('php://input');
看看现在$raw
中有什么(如果有的话)。你应该在那里看到一个 Base64 编码的字符串,你需要解码 - 像这样,如果你需要一个数组:
$info = json_decode(base64_decode($raw), true);
【讨论】:
【参考方案4】:我已经测试了您的代码,它运行良好。问题可能出在您的 PHP 端。我已经在本地服务器以及httpbin
上测试了以下代码来自本地服务器的输出(最新版本的 XAMPP (php 7.3.12)):
Sending request with thw following variables
eyJhZGRpdGlvbmFsX2luZm8iOiIxMy4yLjIiLCJtb2JpbGVfcGluX2Nvbm5lY3QiOiIxMjM0IiwiZGV2aWNlX2luZm8iOiJpUGhvbmUifQ==
result eyJhZGRpdGlvbmFsX2luZm8iOiIxMy4yLjIiLCJtb2JpbGVfcGluX2Nvbm5lY3QiOiIxMjM0IiwiZGV2aWNlX2luZm8iOiJpUGhvbmUifQ==
message ["additional_info": "13.2.2", "mobile_pin_connect": "1234", "device_info": "iPhone"]
代码:
ApiConnector.swift
import Foundation
import UIKit
class ApiConnector
var request: URLRequest
private init(request: URLRequest)
self.request = request
public static var sharedConnector: ApiConnector =
let url = URL(string: "http://localhost/post/index.php")
var request = URLRequest(url: url!)
request.httpMethod = "POST"
request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
let connector = ApiConnector(request: request)
return connector
()
func connect(_ pin: String, completion: @escaping(Result<Dictionary<String, String>, Error>) -> ())
let params: [String : Any] = [
"mobile_pin_connect": pin,
"device_info": UIDevice().model,
"additional_info": UIDevice().systemVersion
]
doRequest(params: params) (data) in
if let data = data
do
let res = try JSONDecoder().decode(Dictionary<String, String>.self, from: data)
completion(.success(res))
catch
completion(.failure(error))
else
print("in else block")
fileprivate func doRequest(params: [String: Any], completion: @escaping (Data?) -> ())
let body = createJsonBody(params)!
self.request.httpBody = body
print("Sending request with thw following variables")
print(String(data: body, encoding: .utf8)!)
URLSession.shared.dataTask(with: self.request) (data, response, error) in
if let error = error
print("Error in request: \(error)")
completion(nil)
let stringResult = String(data: data!, encoding: .utf8)!
print("result \(stringResult)")
let properResult = String(stringResult.map
$0 == "." ? "=" : $0
)
let decodedData = Data(base64Encoded: properResult)
completion(decodedData)
.resume()
fileprivate func createJsonBody(_ params: [String: Any]) -> Data?
do
let jsonData = try JSONSerialization.data(withJSONObject: params)
let body = Data(jsonData).base64EncodedData()
return body
catch
print("Unable to create json body: " + error.localizedDescription, error)
return nil
ViewController.swift
import UIKit
class ViewController: UIViewController
let session = URLSession.shared
override func viewDidLoad()
super.viewDidLoad()
ApiConnector.sharedConnector.connect("1234") (result) in
switch result
case .success(let message):
print("message \(message)")
case .failure(let error):
print(error.localizedDescription)
index.php
echo file_get_contents("php://input");
您可以通过向https://httpbin.org/post发出请求来验证您的代码
输出:
Sending request with thw following variables
eyJkZXZpY2VfaW5mbyI6ImlQaG9uZSIsImFkZGl0aW9uYWxfaW5mbyI6IjEzLjIuMiIsIm1vYmlsZV9waW5fY29ubmVjdCI6IjEyMzQifQ==
result
"args": ,
"data": "eyJkZXZpY2VfaW5mbyI6ImlQaG9uZSIsImFkZGl0aW9uYWxfaW5mbyI6IjEzLjIuMiIsIm1vYmlsZV9waW5fY29ubmVjdCI6IjEyMzQifQ==",
"files": ,
"form": ,
"headers":
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "en-us",
"Content-Length": "108",
"Content-Type": "application/json; charset=utf-8",
"Host": "httpbin.org",
"User-Agent": "SessionTest/1 CFNetwork/1120 Darwin/19.0.0"
,
"json": null,
"origin": "122.173.135.243, 122.173.135.243",
"url": "https://httpbin.org/post"
in else block
如果您运行的是旧版本的 PHP,那么您可能需要 HTTP_RAW_POST_DATA
查看SO 以了解有关 PHP 方面的更多信息。
【讨论】:
以上是关于来自swift的JSON请求在php中显示空数组的主要内容,如果未能解决你的问题,请参考以下文章
在 PHP 中使用来自 AJAX 请求的 JSON 字符串 [关闭]
在 Swift iOS 中解码的 PHP JSON 返回空值