LoginSignup
4
2

More than 1 year has passed since last update.

Swift JSON+Codableで文字列をエラーなくURLに変換する一番簡単な方法

Last updated at Posted at 2023-04-20

まとめ

propertyWrapperを利用することで、JSONの文字列を安全にURLに変換してCodableのstructを生成できるようになります。

概要

JSONをSwiftのStructに落とし込む時にCodableを使うことがあると思います。
StructをCodableに対応すると、JSONのデータをJSONDecoderを通して、数値、文字列、Boolなどに変換したStructに変換することができます。

しかし、URLの場合は、JSONの文字列がinit(string:)の結果でnilになるような文字列の場合、DecodingErrorとなってstructとして生成できなくなってしまいます。

例えば以下のようなstructです。

struct MyUser: Codable {
    let id: Int
    let name: String
    let url: URL
}

これに対し、urlが問題なくURLとして生成できる文字列であればstruct生成されますが、urlがURLではない文字列がくると、structが作られず、JSONDecoderがエラーを吐いて処理が失敗します。

        let data = """
        {
          "id": 1234,
          "name": "Hello World!",
          "url": ""
        }
        """.data(using: .utf8)!
        
        let decoder = JSONDecoder()
        let user = try decoder.decode(MyUser.self, from: data) //DecodingError
        print(user.url)

対応

まず、JSONからURLに変換する用の、Codableを付与したpropertyWrapper structを用意します。
JsonUrlとして用意しました。
init処理では、decoderによってデコードされたwrappedValueのStringをprojectedValueとしてURLに設定します。

@propertyWrapper
struct JsonUrl: Codable {
    var wrappedValue: String
    var projectedValue: URL?
    
    init(from decoder: Decoder) throws {
        wrappedValue = try String(from: decoder)
        projectedValue = URL(string: wrappedValue)
    }
}

次に、URLとして設定するプロパティに@JsonUrlを付与し、Stringにします。
letはvarにしないとビルドが通りません。

struct MyUser: Codable {
    let id: Int
    let name: String
    
    @JsonUrl
    var url: String
}

あとは、structを利用する側は、URLとして利用する場合は$を付与して利用すればOKです。
decoderがエラーを出すことなく処理が可能です。

        let data = """
        {
          "id": 1234,
          "name": "Hello World!",
          "url": ""
        }
        """.data(using: .utf8)!
        
        let decoder = JSONDecoder()
        let user = try decoder.decode(MyUser.self, from: data) 
        print(user.$url) // nil

過去のSwift JSON+Codableリンク

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2