ios — PHP / Swift JSON Сериализация массива списка элементов приводит к нулю элементов

Привет, я новичок здесь и очень новичок в программировании, но постараюсь прояснить этот вопрос настолько, насколько это возможно. По сути, у меня есть таблица, созданная из запроса 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 я только что установил переменную userID равной 5, чтобы протестировать ее, и прошел общий процесс запроса + сериализации:

@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 Dictionary» я получаю «Не удалось привести значение типа ‘__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]]

1

Решение

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

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

1

Другие решения

Я думаю, что вы должны сначала привести в порядок свой код JSON-разбора, прежде чем начинать разбираться с dataTask и тому подобное. Бросив в некоторых Codable чтобы стать более быстрым, вы получите что-то вроде

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 перед тем как сделать это) чтобы узнать что вы кидаете в свой парсер (JSONDecoder).

0

По вопросам рекламы [email protected]