可选的URL导致JSON解码在Swift中失败4

问题描述:

我想弄清楚为什么使用可选的URL导致我的JSON解码使用Swift 4失败。我已经倒过WWDC“Whats new in Foundation”视频,苹果游乐场的例子,和互联网上的一堆地方,但还没有找到解决方案。可选的URL导致JSON解码在Swift中失败4

这是我创建的一个测试来显示问题。之所以这样说,是我的JSON数据:

let json = """ 
{ 
    "kind" : "", 
    "total" : 2, 
    "image_url" : "https://www.myawesomeimageURL.com/awesomeImage.jpg" 
} 
""".data(using: .utf8)! 

这是我的结构:

struct BusinessService: Decodable { 
    let kind: String? 
    let total: Int 
    let image_url : URL? 
} 

这里的地方我把它序列化:

let myBusiness = try? JSONDecoder().decode(BusinessService.self, from: json) 
print(myBusiness) 

现在的问题是,如果我收到JSON image_url丢失的数据,json解码失败并且给我零。

我很困惑,为什么“kind”可以是一个可选的字符串,并且不会导致json解码在没有值时失败,但是image_url不能成为可选的URL而不会导致json失败。

我一直在试图找出两天现在没有运气。有没有人有任何洞察,为什么这会失败?

我注意到了另一个难题,那就是json中的image_url实际上不必是有效的图像URL。我可以键入任何字符串,我的结构被序列化,所以我想也许我误解了这是如何工作的。我认为只有当网址可以转换为有效的网址时,该网址才会自动填充,并且不会发生。

任何有识之士将不胜感激。

这适用于我的预期。设置image_urlnull或离开它完全导致有效BusinessService得到与为image_url领域nil值解码:

struct Example: Decodable { 
    let url: URL? 
} 

// URL is present. This works, obviously. 
try JSONDecoder().decode(Example.self, from: """ 
    { "url": "foo" } 
    """.data(using: .utf8)!) 

// URL is missing, indicated by null. Also works. 
try JSONDecoder().decode(Example.self, from: """ 
    { "url": null } 
    """.data(using: .utf8)!) 

// URL is missing, not even the key is present. Also works. 
try JSONDecoder().decode(Example.self, from: """ 
    {} 
    """.data(using: .utf8)!) // works, too 

唯一的问题出现时,我提供一个无效的URL值,如为空字符串场。所以我想这是你的问题?

// This throws: "Invalid URL string." 
try JSONDecoder().decode(Example.self, from: """ 
    { "url": "" } 
    """.data(using: .utf8)!) 

你必须通过发送null或离开整个线路输出发送对URL字段为“无”的值,而不是发送一个空字符串。

我很困惑,为什么“种”可以是一个可选的字符串,并不会导致JSON解码时,它没有任何价值的失败,但不会导致JSON失败IMAGE_URL不能是一个可选的URL。

区别在于JSON中的""是有效的String值,但不是有效的URL。

+0

非常感谢你的解释。这整个周末都让我疯狂。我不使用JSON太多,所以我没有意识到null是一个有效的值。 这是一个耻辱,我使用的API(Yelp)通过“”而不是null。我将不得不查看json容器(我认为)来解决这个问题。 感谢您的帮助! – SN81

+0

乐意帮忙!“空”的情况总是有点棘手,因为很容易混淆空字符串和缺少的字符串。 Swift中的'Optional'类型使得这一点更好一些,因为当字符串丢失时会得到'.none',而当字符串存在时会得到'.some(“”)',但是是空的。确实,通过''“'丢失URL是一个糟糕的选择。 – zoul