7

オプション URL を使用すると、Swift 4 を使用して JSON デコードが失敗する理由を理解しようとしています。WWDC の「Foundation の新機能」ビデオ、Apples Playground の例、およびインターネット上の多くの場所に既に注がれていますが、解決策を見つけていません。

これは、問題を示すために作成したテストです。これが私の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)

ここで、問題は、image_url が欠落している json データを受信した場合、json のデコードが失敗し、nil が返されることです。

「種類」がオプションの文字列になり、値がない場合にjsonのデコードが失敗しない理由について混乱していますが、jsonを失敗させずにimage_urlをオプションのURLにすることはできません。

私はこれを2日間理解しようとしてきましたが、運がありません。なぜこれが失敗するのかについての洞察を持っている人はいますか?

パズルのもう 1 つのピースに気付きました。それは、json の image_url が実際には有効な画像 URL である必要はないということです。任意の文字列を入力でき、構造体がシリアル化されるため、これがどのように機能するかを誤解している可能性があります。URL が有効な URL に変換できる場合にのみ、URL が自動的に入力されると考えていましたが、それは起こっていません。

これに対する洞察は大歓迎です。

4

2 に答える 2

1

このケースを処理するために実装できる簡単な調整が 1 つあります。try catch ブロックを使用して、url アイテムをデコードできます。Invalid URL Caseがある場合は、try catch ブロックに null 値を割り当てることができます。

    struct Example: Codable {
    let url: URL?
    
    private enum CodingKeys: String, CodingKey {
      case url
    }
    
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        do {
            url = try container.decode(URL.self, forKey: .url)
        }catch( _) {
            url = nil
        }
    }
}

注: Swift Playground では、上記のコードは依然としてクラッシュを引き起こしますが、通常の Xcode プロジェクトでは期待どおりに動作します。

于 2021-03-27T14:42:20.370 に答える