我有一个iOS应用程序(Swift),它编码一些数据并执行JSONSerialization并创建一个JSON对象。我的代码如下,我尽力保持整洁,所以我希望它有意义:
struct Order: Codable {
let idQty: [FoodIdAndQuantity]
let collection: String
let name: String
let phone: Int
let doorNum: Int
let street: String
let postcode: String
}
struct FoodIdAndQuantity: Codable {
let itemId: Int
let qty: Int
}
class CheckoutServer: NSObject, URLSessionDataDelegate {
var inputValuesForItemAndQuantity = [Int:Int]()
var idQty = [FoodIdAndQuantity]()
var collection = String()
var name = String()
var phone = Int()
var doorNum = Int()
var street = String()
var postcode = String()
var request = URLRequest(url: NSURL(string: "http://192.168.1.100/api/AddOrder.php")! as URL)
func sendToDatabase() {
for(key,value) in inputValuesForItemAndQuantity {
idQty.append(FoodIdAndQuantity(itemId: key, qty: value))
}
let order = Order(idQty: idQty,collection: collection,name: name,phone: phone,doorNum: doorNum,street: street,postcode: postcode)
let encodedOrder = try? JSONEncoder().encode(order)
var json: Any?
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
if let data = encodedOrder {
json = try? JSONSerialization.jsonObject(with: data, options: .allowFragments)
if var json = json {
if JSONSerialization.isValidJSONObject(json) {
do {
json = try JSONSerialization.data(withJSONObject: json, options: .prettyPrinted)
} catch {
print("There was a problem creating the JSON object")
}
} else {
print("not valid JSON")
}
}
}
let postParameters = "json="+String(describing: json!)
print(String(describing: json!)) //Print JSON for debugging purposes
request.httpBody = postParameters.data(using: .utf8)
let defaultSession = URLSession(configuration: URLSessionConfiguration.default)
let task = defaultSession.dataTask(with: request) { (data, response, error) in
if error != nil {
print("Failed to download data at Menu Type Items")
} else {
print("Data uploaded")
}
}
task.resume()
}
}
所以上面的代码执行以下操作:
我已经打印了json对象,该对象在XCode中被发布回控制台,其外观如下:
{
collection = Delivery;
doorNum = 99;
idQty = (
{
itemId = 17;
qty = 5;
},
{
itemId = 1;
qty = 3;
}
);
name = James;
phone = 012345667;
postcode = LXU49RT;
street = Hope Street;
}
接下来,我将转到我的服务器/ API,它接受POST参数。
下面是我的AddOrder.php页面:
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
require_once dirname(__FILE__) . '/DbOperation.php';
$json = $_POST["json"];
$db = new DbOperation();
$json = $db->addOrder($json);
}
以下是我的DbOperation addOrder函数:
public function addOrder($json) {
require dirname(__FILE__) . '/../../dbconnect.php';
$decoded = json_decode($json);
$collection = $decoded{"collection"};
$stmt2 = $pdo->prepare("INSERT INTO TestTable (collection) VALUES (:collection)");
$stmt2->bindParam(':collection',$collection);
$stmt2->execute();
}
值得注意的是,在我尝试修复此问题时,我在我的数据库中创建了一个测试表,它只存储了JSON的集合元素。
我遇到的问题是,当我运行我的应用程序并发送数据时,没有任何内容存储在数据库中,而我的apache error.log文件说Column'collection'不能为null。所以我假设我在PHP的某些时候错误地处理POST参数。除非故障位于Swift级别,如果管理员询问,我会将Swift标签添加到此帖子中。
完整错误如下:
[Wed Feb 28 15:44:55.178184 2018] [:error] [pid 520] [client 192.168.1.46:52400] PHP Fatal error: Uncaught PDOException: SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'collection' cannot be null in /var/www/api/DbOperation.php:111\nStack trace:\n#0 /var/www/api/DbOperation.php(111): PDOStatement->execute()\n#1 /var/www/api/AddOrder.php(16): DbOperation->addOrder(NULL)\n#2 {main}\n thrown in /var/www/api/DbOperation.php on line 111
我试过的
我已经尝试将AddOrder.php页面改为以下内容:
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
require_once dirname(__FILE__) . '/DbOperation.php';
//$json = $_POST["json"];
$json = json_decode(file_get_contents('php://input'),true);
$db = new DbOperation();
$json = $db->addOrder($json);
}
你的快速代码没有多大意义。您有使用JSONEncoder
将swift对象编码为Data的代码。如果成功,则使用JSONSerialization
将数据转换回Swift对象。如果成功,则使用JSONSerialization.data(withJSONObject:options:)
将Swift对象转换回JSON数据,然后使用String(describing:)
将您疯狂的过度处理的JSON数据转换为字符串,这非常非常错误。
摆脱所有代码。试试这个:
func sendToDatabase() {
for(key,value) in inputValuesForItemAndQuantity {
idQty.append(FoodIdAndQuantity(itemId: key, qty: value))
}
let order = Order(idQty: idQty,collection: collection,name: name,phone: phone,doorNum: doorNum,street: street,postcode: postcode)
guard let encodedOrder = try? JSONEncoder().encode(order) else { return }
request.httpBody = encodedOrder
let defaultSession = URLSession(configuration: URLSessionConfiguration.default)
let task = defaultSession.dataTask(with: request) { (data, response, error) in
if error != nil {
print("Failed to download data at Menu Type Items")
} else {
print("Data uploaded")
}
}
task.resume()
}
以下是无效的代码,应该抛出致命的“不能使用stdClass类型的对象作为数组”:
$decoded = json_decode($json);
$collection = $decoded{"collection"};
你可能想要这个:
$decoded = json_decode($json, true);
$collection = $decoded["collection"];
或这个:
$decoded = json_decode($json);
$collection = $decoded->collection;