如何从Swift(iOS)应用程序处理PHP中传入的JSON?

问题描述 投票:1回答:2

我有一个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()
    }
}

所以上面的代码执行以下操作:

  • 创建一个名为“order”的可编码对象。
  • 创建对我的API的POST请求。
  • 通过POST参数传递编码的JSON对象。

我已经打印了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);

}
php json swift
2个回答
2
投票

你的快速代码没有多大意义。您有使用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()
}

1
投票

以下是无效的代码,应该抛出致命的“不能使用stdClass类型的对象作为数组”:

$decoded = json_decode($json);
$collection = $decoded{"collection"};

你可能想要这个:

$decoded = json_decode($json, true);
$collection = $decoded["collection"];

或这个:

$decoded = json_decode($json);
$collection = $decoded->collection;
© www.soinside.com 2019 - 2024. All rights reserved.