Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Json URL中的Umlaut无法编码(Swift)-怎么办?_Json_Swift_Url_Decode_Codable - Fatal编程技术网

Json URL中的Umlaut无法编码(Swift)-怎么办?

Json URL中的Umlaut无法编码(Swift)-怎么办?,json,swift,url,decode,codable,Json,Swift,Url,Decode,Codable,使用Swift-4.1、Xcode-9.3.1、iOS-11.3.1 我使用可编码协议来解码JSON文件。除了在URL中有一个国际化域名(在本例中,带有一个德语Umlaut“ä”)的那一刻(例如:),一切都正常 这会导致以下代码中出现解码器错误: func loadJSON(url: URL) -> Media? { do { let data = try Data(contentsOf: url) let decoder = JSONDecoder

使用Swift-4.1、Xcode-9.3.1、iOS-11.3.1

我使用可编码协议来解码JSON文件。除了在URL中有一个国际化域名(在本例中,带有一个德语Umlaut“
ä
”)的那一刻(例如:),一切都正常

这会导致以下代码中出现解码器错误:

func loadJSON(url: URL) -> Media? {
    do {
        let data = try Data(contentsOf: url)
        let decoder = JSONDecoder()
        let media = try decoder.decode(Media.self, from: data)
        return media
    } catch {
        print("error:\(error)")
    }
    return nil
}
错误消息是:

The Codable protocol does not seem to be able to decode this URL form
my JSON-file into the needed Struct.
以下是结构:

struct Media: Codable {
    var publisher: [MediaPublisher]
}

struct MediaPublisher: Codable {
    var title: String?
    var homepage_url: URL?
}
以下是JSON摘录:

    {
      "publisher": [
        {
          "title"             : "Rhätische-Zeitung",
          "homepage_url"      : "http://www.rhätische-zeitung.ch",
        }
      ]
    }
由于JSON文件来自外部,因此我无法控制内容。因此,替换JSON中的URL不是一个选项! (因此,我无法将JSON中的URL替换为公认的国际化形式,例如:
www.xn--rhtische zeitung wnb.ch

我知道有一些技术可以将自定义初始值设定器放入结构定义中(请参见下面的试用…)-但是由于对Codable来说是新的,我不知道如何解决当前的URL Umlaut问题。我在下面放置的自定义初始化器对于问题的URL返回nil。我需要改变什么

或者有没有另一种方法可以使用Umlaut对URL进行JSON解码

这是结构,这次使用的是自定义初始化器:

(至少这样,我可以摆脱上面的错误消息…但URL现在似乎为零,这也不是我想要的)


我只是被同样的问题绊倒了。这个解决方案实际上相当简单,在我的简短测试中效果很好

这样做的目的是不让解码器将值解码为URL,因为它希望后面的字符串采用某种格式。我们可以做的是直接将值解码为字符串,并手动将其转换为URL

我写了一个小小的扩展来完成这项工作:

extension KeyedDecodingContainer {

    /// Decodes the string at the given key as a URL. This allows for special characters like umlauts to be decoded correctly.
    func decodeSanitizedURL(forKey key: KeyedDecodingContainer<K>.Key) throws -> URL {
        let urlString = try self.decode(String.self, forKey: key)

        // Sanitize string and attempt to convert it into a valid url
        if let urlString = urlString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed), let url = URL(string: urlString) {
            return url
        }

        // Throw an error as the URL could not be decoded
        else {
            throw DecodingError.dataCorruptedError(forKey: key, in: self, debugDescription: "Could not decode \(urlString)")
        }
    }

}
希望这能有所帮助,即使问题有点老了

extension KeyedDecodingContainer {

    /// Decodes the string at the given key as a URL. This allows for special characters like umlauts to be decoded correctly.
    func decodeSanitizedURL(forKey key: KeyedDecodingContainer<K>.Key) throws -> URL {
        let urlString = try self.decode(String.self, forKey: key)

        // Sanitize string and attempt to convert it into a valid url
        if let urlString = urlString.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed), let url = URL(string: urlString) {
            return url
        }

        // Throw an error as the URL could not be decoded
        else {
            throw DecodingError.dataCorruptedError(forKey: key, in: self, debugDescription: "Could not decode \(urlString)")
        }
    }

}
required init(from decoder: Decoder) throws {
    let values = try decoder.container(keyedBy: CodingKeys.self)
    self.url = try values.decodeSanitizedURL(forKey: .url)
}