【问题标题】:Retrieved JSON data not decoding to custom struct in xcode 12检索到的 JSON 数据未解码为 xcode 12 中的自定义结构
【发布时间】:2021-09-02 14:02:42
【问题描述】:

我目前正在学习如何从 apache 服务器上的 mySQL 数据库中检索编码的 JSON 数据,并将 JSON 解码为我自己的自定义结构的实例;

struct Person: Codable, FetchableRecord, MutablePersistableRecord {
    var id: Int64
    var firstName: String
    var lastName: String
}

这是我在 xcode 上的网络请求方法

func dataRequestDownload() {
        let baseURL = URL(string: "http://example.com/db_request.php?action=request")
        
        DispatchQueue.main.async {
            if let url = baseURL {
                let task = URLSession.shared.dataTask(with: url) { data, response, error in
                    if let data = data {
                        let decoder = JSONDecoder()
                        let person = try? decoder.decode(Person.self, from: data)
                        print(person)
                    }
                }
                task.resume()
            }
        }
    }
}

我的问题是person 打印为nil,这让我认为数据没有被正确解码。

这是我的 GET 请求的 PHP 脚本。

<?php
    
    
$con=mysqli_connect("127.0.0.1","root","example_password","example_database");
 

if (mysqli_connect_errno())
{
  echo "Failed to connect to MySQL: " . mysqli_connect_error();
}
 

$sql = "SELECT * FROM person";
 
if ($result = mysqli_query($con, $sql))
{
    // If so, then create a results array and a temporary one
    // to hold the data
    $resultArray = array();
    $tempArray = array();
 
    // Loop through each row in the result set
    while($row = $result->fetch_object())
    {
        // Add each row into our results array
        $tempArray = $row;
        array_push($resultArray, $tempArray);
    }
 
    // Finally, encode the array to JSON and output the results
    echo json_encode($resultArray);
}
 
// Close connections
mysqli_close($con)
?>

最后我不确定这个信息是否重要,但在 mySQL 数据库中,表的设置就像我的结构一样,其中 id 是PRIMARY 键。如果需要更多信息,请在 cmets 中告诉我,但据我所知,这似乎与我的问题有关。

编辑:其他一些可能重要的信息是当我调用print(data)print(response)

48 bytes
{ Status Code: 200, Headers {
    Connection =     (
        "Keep-Alive"
    );
    "Content-Length" =     (
        48
    );
    "Content-Type" =     (
        "text/html; charset=UTF-8"
    );
    Date =     (
        "Thu, 17 Jun 2021 18:43:02 GMT"
    );
    "Keep-Alive" =     (
        "timeout=5, max=100"
    );
    Server =     (
        "Apache/2.4.46 (Win64) PHP/7.3.21"
    );
    "X-Powered-By" =     (
        "PHP/7.3.21"
    );
} })

网址当然不受此限制。

根据 cmets 中的请求;这样做了

let object = try? JSONSerialization.jsonObject(with: data)
print(object)

我明白了

Optional(<__NSSingleObjectArrayI 0x281510080>(
{
    firstName = John;
    id = 0;
    lastName = Doe;
}
)
)

Edit2:运行时

do {
      let person = try decoder.decode([Person].self, from: data)
      print(person)
  } catch {
      print(error)
   }

出现如下错误

typeMismatch(Swift.Int64, Swift.DecodingError.Context(codingPath [_JSONKey(stringValue: "Index 0", intValue: 0),
CodingKeys(stringValue: "id", intValue: nil)], debugDescription:
"Expected to decode Int64 but found a string/data instead.", underlyingError: nil))

这是访问 URL 时的实际 JSON

[{"id":"0","firstName":"John","lastName":"Doe"}]

【问题讨论】:

  • 您能否提供从您的 API 请求返回的 JSON 示例?
  • 我现在正在写一个答案。同时,您能否发布实际的 JSON,以便我确定(即,当您访问 URL 时返回的内容 - 而不是您尝试使用 Swift 解码时发生的情况)
  • 该错误(自编辑以来)告诉您 id 是 JSON 中的字符串。调整您的 Person 模型以使用 String 来表示 id 而不是 Int64 的类型,或者调整您的数据库和/或 PHP 代码以使用数字而不是字符串作为 id。
  • 添加到答案中
  • 您可能需要阅读stackoverflow.com/questions/1390983/… 以获得一些关于让您的PHP 将id 编码为Int 的提示。您可以看到,在 JSON 中,它显然是 String,所以这在 Swift 方面不是问题。

标签: php ios json swift xcode


【解决方案1】:

解码 JSON 时,使用do/try/catch 很有帮助,这样您就可以真正看到错误是什么。

看起来,在这种情况下,您有一个数组(从您的 PHP 代码中可以清楚地看出),但您正在尝试解码单个对象。试试这个:

do {
  let person = try decoder.decode([Person].self, from: data)
  print(person)
} catch {
  print(error)
}

然后,由于您将在 person 中拥有一个数组(此时可能更准确地命名为 people),您需要使用类似 person.first 的方式访问它


根据您编辑中添加的代码进行更新:

该错误告诉您 id 是 JSON 中的 String。调整您的Person 模型以使用String 来表示id 的类型而不是Int64,或者调整您的数据库和/或PHP 代码以使用数字而不是String 来表示id

【讨论】:

  • 这很有帮助,我可能不得不在某些时候重写 php。至于上面的代码,我即将发布对结果和实际 JSON 的编辑。
猜你喜欢
  • 2014-01-18
  • 1970-01-01
  • 2021-01-21
  • 2013-08-30
  • 2020-10-27
  • 2021-06-09
  • 2023-04-06
  • 2020-11-01
  • 1970-01-01
相关资源
最近更新 更多