PHP / Swift JSON Сериализация массива списка элементов приводит к нулевым элементам - PullRequest
0 голосов
/ 24 мая 2018

Привет, я новичок здесь и очень плохо знаком с программированием, но постараюсь прояснить этот вопрос как можно яснее.По сути, у меня есть таблица, созданная из запроса SQL, которая дает список элементов / объектов в инвентаризации пользователя на основе их идентификатора пользователя.Таблица выглядит примерно так (где userID равен 5) - извиняюсь, у меня пока недостаточно репов для публикации фотографий: инвентарь пользователя 5

Я собирался иметь tableView в Swiftзаполнить эту таблицу, но когда у меня возникли проблемы с преобразованием ответа, я вместо этого просто создал отдельный ViewController с кнопкой для запуска функции checkInventory, чтобы я мог распечатать все данные и посмотреть, где проблема.

Сначала моя функция PHP для проверки инвентаризации:

public function getUserInventory($userID) {

$returnValue = array();

$sql = "select aObjects.objectID, objectDescription from aUsers join aInventory on aUsers.userID = aInventory.userID join aObjects on aInventory.objectID = aObjects.objectID where aUsers.userID='" .$userID. "'" ;

try {

$statement = $this->conn->prepare($sql);

$statement->execute();

$statement->bind_result($objectID, $objectDescription);

}

catch (PDOException $e) 

{

print $e->getMessage();

}

$result = $statement->get_result();

if ($result != null && (mysqli_num_rows($result) >= 1)) 

{


$row = $result->fetch_all(MYSQLI_ASSOC);

if (!empty($row)) {

$returnValue = $row;

}

}

return $returnValue;

}

Строка исключения PDO может быть ненужной / неправильной, потому что я использую mysqli, но независимо от этого здесь есть другой файл PHP, которыйвызывает эту функцию:

<?php 

set_include_path('.:/testservice/');

$data = json_decode(file_get_contents('php://input'), true);
$userID = $data["userID"];
//$userID = htmlentities($_GET["userID"]); <--- for testing

include 'Conn.php';  /* connection file */
include 'aSQLDao.php'; /* rest of php file */

$dao = new aSQLDao();
$dao->openConnection();
$userInventory = $dao->getUserInventory($userID);

echo json_encode($userInventory);
return;

$dao->closeConnection();

?>

Я на 90% уверен, что корень моей проблемы заключается в том, что мой PHP не выдает вывод JSON, который Swift может правильно прочитать.Когда я использую почтальон для проверки PHP с userID = 5, я получаю объект, который выглядит красиво, но, похоже, имеет основную проблему с его форматом:

[
{
    "objectID": 1,
    "objectDescription": "alien"
},
{
    "objectID": 2,
    "objectDescription": "forestMonster"
},
{
    "objectID": 10,
    "objectDescription": "tank"
},
{
    "objectID": 9,
    "objectDescription": "fish"
}
]

В swift я только что установил переменную userID5, чтобы проверить его и пройти через общий процесс запроса + сериализации:

@IBAction func inventoryButtonTapped(_ sender: Any) {

        let userID = "5"
        let myURL = URL(string: "http://myIP/testservice/inventoryCheck.php");
        var request = URLRequest(url:myURL!);
        request.httpMethod = "GET"
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        request.setValue("application/json", forHTTPHeaderField: "Accept")


        let getString = ["userID": userID] as [String: String]
        do {
            request.httpBody = try JSONSerialization.data(withJSONObject: getString, options: .prettyPrinted)
                   } catch let error {
                        print(error.localizedDescription)
                        displayMessage(userMessage: "Something went wrong")
                       return
                }
        let task = URLSession.shared.dataTask(with: request) {
                       data, response, error in

                        if error != nil {
                           self.displayMessage(userMessage: "Could not perform")
                            print("error=\(String(describing: error))")
                            return
                        }

                        do {
                            let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! NSDictionary

                            print(json)

Есть и другое, но из-за точек останова я не могу правильно преобразовать эти данные на этапе JSONSerialization.При использовании словаря «as! NS» я получаю «Не удалось преобразовать значение типа« __NSArrayM »(0x10ad29a88) в« NSDictionary »(0x10ad2b1a8)." ошибка.

При использовании "as! NSArray" я получаю пустой набор паратезов .Я попытался также использовать Array>, что привело к пустому набору скобок.Я также попытался установить userID в int, но из того, что я прочитал, это не должно повлиять на это.

Я прошу прощения, если здесь отсутствуют какие-либо подробности.Так как это кажется довольно простым случаем переноса таблицы SQL в UITableView, я предполагаю, что я либо пропускаю основную часть, либо выполняю неправильный набор операций.

ОБНОВЛЕНИЕ: Я выяснил, что Сервер просто не получает мой ключ userID правильно, что странно, но, по крайней мере, надеюсь, что PHP или Swift неверны - предположим, что оба предоставленных ответа будут работать, если переменная была отправленаправильно к сценарию

РЕШЕНО: По какой-то причине эта проблема была решена при изменении HTTPRequest с GET на POST - казалось, проблема с вводом PHP, не работающим для запроса GET.Я обновлю этот пост более конкретными деталями для дальнейшего использования, когда выясню, как заставить запрос GET работать должным образом, поскольку это должен быть GET, а не POST.Оба предоставленных ответа верны с точки зрения изменения NSDictionary на NSArray или [[String: Any]]

Ответы [ 2 ]

0 голосов
/ 24 мая 2018

Полагаю, вы должны сначала привести в порядок свой код JSON-разбора, прежде чем начинать работать с вашим dataTask и тому подобным.Добавив Codable, чтобы стать более Swifty, вы получите что-то вроде

import Cocoa

let jsonData = """
[
{
    "objectID": 1,
    "objectDescription": "alien"
},
{
    "objectID": 2,
    "objectDescription": "forestMonster"
},
{
    "objectID": 10,
    "objectDescription": "tank"
},
{
    "objectID": 9,
    "objectDescription": "fish"
}
]
""".data(using: .utf8)!

struct MyObject: Codable {
    let id: Int
    let description: String

    private enum CodingKeys: String, CodingKey {
        case id = "objectID"
        case description = "objectDescription"
    }
}



do {
    let obj = try JSONDecoder().decode([MyObject].self, from:jsonData)
    print(obj)
} catch {
    print(error)
}

Это даст вам гораздо больше удобных объектов Swift с минимальными усилиями, а JSONDecoder обычно скажет вам, если что-то не так с JSONдоставлено (чего нет в данном случае).

Имея это, вы должны распечатать необработанные данные (преобразовав их в String перед тем, как сделать это), чтобы узнать, что вы бросаете в свой парсер(* 1 010 *). * * +1011

0 голосов
/ 24 мая 2018

Строка десериализации находится здесь:

let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! NSDictionary

Вы пытаетесь принудительно привести к NSDictionary.Проблема в том, что ваша структура данных представляет собой массив.

[ // this will convert to an array
    { // this will convert to a dictionary
        "objectID": 1,
        "objectDescription": "alien"
    },
    ...
]

У вас есть несколько вариантов.Вы можете изменить ее JSON для создания словаря, или вы можете изменить свой десериализатор для ожидания массива.

Вот второй случай в коде:

//: Playground - noun: a place where people can play

import UIKit

var dataStr = """
[ { "objectID": 1, "objectDescription": "alien" }, { "objectID": 2, "objectDescription": "forestMonster" }, { "objectID": 10, "objectDescription": "tank" }, { "objectID": 9, "objectDescription": "fish" }]
"""
var data = dataStr.data(using: .utf8)

let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSArray

И результат:

xcode result

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...