[英]Parsing JSON Data Swift “Thread 4: Fatal error: Unexpectedly found nil while unwrapping an Optional value”
I am trying to parse some JSON data returned from an API call.我正在尝试解析从 API 调用返回的一些 JSON 数据。 The path I want to navigate is media > faces > points.我要导航的路径是媒体 > 面孔 > 点。 I can navigate to faces but getting points is the issue.我可以导航到面孔,但获得积分是问题所在。
here is code这是代码
let dictionary = try JSONSerialization.jsonObject(with: data!, options:.mutableContainers) as? [String:Any]
let media = dictionary!["media"] as? [String: Any]
print(media!["faces"]) // Works see the returned data below
let faces = media!["faces"] as? [String: Any]
print(faces!["points"]) // Thread 4: Fatal error: Unexpectedly found nil while unwrapping an Optional value
API returned data for print(media!["faces"]) API 返回打印数据(media!["faces"])
{
angle = "1.2222";
"appearance_id" = 0;
"detection_score" = 1;
duration = "00:00:00";
"face_uuid" = "78338d20-9ced-11ea-b153-0cc47a6c4dbd";
height = "74.31999999999999";
"media_uuid" = "fec83ac3-de00-44f0-ad5b-e1e990a29a8c";
"person_id" = "";
points = (
{
name = "basic eye left";
type = 512;
x = "85.16";
y = "86.62";
},
{
name = "basic eye right";
type = 768;
x = "110.92";
y = "86.66";
}
Since you are a beginner I'm helping you out.由于您是初学者,我正在帮助您。 These questions have been asked many times (There is a high chance you get duplicate flag).这些问题已经被问过很多次(你很有可能得到重复的标志)。 Here is how you avoid these kinds of errors, try not to use force-unwraps (this symbol !
) anywhere without any exception to avoid these errors.以下是避免此类错误的方法,请尽量不要在任何地方使用强制展开(此符号!
)以避免这些错误。 Instead of if let
you can use guard let
, it's a personal choice.而不是if let
你可以使用guard let
,这是个人选择。
if let data = data,
let dictionary = try JSONSerialization.jsonObject(with: data, options:.mutableContainers) as? [String: Any],
let media = dictionary["media"] as? [String: Any],
let faces = media["faces"] as? [[String: Any]],
let points = faces[0]["points"] {
print(points)
}
Edit: Since "faces"
parameter is an array you need to parse them as an Array
and not as Dictionary
.编辑:由于"faces"
参数是一个数组,您需要将它们解析为Array
而不是Dictionary
。 The above example shows how to get to the first set of "points"
.上面的例子展示了如何到达第一组"points"
。
Update: Better approach would be to use JSONDecoder
.更新:更好的方法是使用JSONDecoder
。 Here's how: Create this struct outside the class:方法如下:在 class 之外创建此结构:
struct Response: Codable { var media: Media }
struct Media: Codable { var faces: [Face] }
struct Face: Codable { var points: [Point] }
struct Point: Codable { }
And then decode like this:然后像这样解码:
if let data = data,
let response = try JSONDecoder().decode(Response.self, from: data) {
print(response.media.faces[0].points)
}
The main problem here is that you are force unwrapping optionals that you can't guarantee have a value - and when they don't have one that's causing a fatal error.这里的主要问题是你强制解包你不能保证有一个值的选项 - 当它们没有一个导致致命错误的时候。
A better approach is to unwrap the variables safely and throw an error if you need to handle it.更好的方法是安全地解包变量并在需要处理时抛出错误。 I've tried to show a few different ways to do that below.我试图在下面展示几种不同的方法来做到这一点。
guard let data = data else { return }
do {
let dictionary = try JSONSerialization.jsonObject(with: data, options: .mutableContainers) as? [String:Any]
guard let media = dictionary?["media"] as? [String: Any] else { throw MyError.mediaNotFoundError }
if let faces = media["faces"] as? [String: Any] {
print(faces)
guard let points = faces["points"] else { throw MyError.pointsNotFound}
print(points)
} else {
throw MyError.facesNotFound
}
} catch {
// Handle error here
}
Note, I have used a custom error enum.请注意,我使用了自定义错误枚举。 I would also advise adding a localised description to it in order to add more details for debugging.我还建议为其添加本地化描述,以便为调试添加更多详细信息。
enum MyError: Error {
case mediaNotFoundError
case facesNotFound
case pointsNotFound
}
I would also recommend reading this answer here for a more in-depth explanation on optionals.我还建议在此处阅读此答案,以更深入地解释选项。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.