2017-11-21 23 views
0

に私は私のバックエンドは、このようなオブジェクトを返します(迷惑)な状況があります。各プロパティは、その最初の要素として文字列を保持する配列であるコード可能なオブジェクトマッピング配列の要素の文字列

{ 
"user": { 
     "name": [ 
      "John" 
     ], 
     "familyName": [ 
      "Johnson" 
     ] 
    } 
} 

を。私のデータモデルではstruct私は配列として各プロパティを宣言することができますが、それは本当に醜いだろう。

struct User: Codable { 
    var user: String 
    var familyName: String 
} 

しかし、これはもちろん、タイプが一致しないため、エンコード/デコードに失敗します。今その

extension Map { 
    public func firstFromArray<T>(key: String) -> T? { 
     if let array = self[key].currentValue as? [T] { 
      return array.first 
     } 
     return self[key].currentValue as? T 
    } 
} 

しかし:今まで私はそれで私はinit方法この機能により各値assig Stringタイプとして、私のモデルでは、私のプロパティを宣言することができ、MapオブジェクトとcurrentValueプロパティを提供ObjectMapperライブラリを使用しました私はCodableのアプローチに変換している、私はそのようなマッピングを行う方法を知らない。何か案は?

答えて

1

私の傾向は、例えば、入ってくるデータにモデルを適用し、アプリケーションで使用するための計算されたプロパティを作成することです

struct User: Codable { 
    var user: [String] 
    var familyName: [String] 

    var userFirstName: String? { 
     return user.first 
    } 

    var userFamilyName: String? { 
     return familyName.first 
    } 
} 

これは、簡単にデータ構造が符号化/復号化をオーバーライドのメンテナンスコストをかけずに入ってくるとパロディを維持することができます。

デザインにうまくいく場合は、UIラッパーのTypeまたはViewModelを使用して、基になるモデルとその表示をより明確に区別することもできます。

+0

ありがとうございます。私は 'init'をオーバーライドするよりも、この方が好きです。 –

1

あなたはinit(from decoder: Decoder)を上書きすることができます。

let json = """ 
{ 
    "user": { 
     "name": [ 
     "John" 
     ], 
     "familyName": [ 
     "Johnson" 
     ] 
    } 
} 
""" 

struct User: Codable { 
    var name: String 
    var familyName: String 

    init(from decoder: Decoder) throws { 
     let container:KeyedDecodingContainer = try decoder.container(keyedBy: CodingKeys.self) 
     let nameArray = try container.decode([String].self, forKey: .name) 
     let familyNameArray = try container.decode([String].self, forKey: .familyName) 
     self.name = nameArray.first! 
     self.familyName = familyNameArray.first! 
    } 

    enum CodingKeys: String, CodingKey { 
     case name 
     case familyName 
    } 
} 

let data = json.data(using: .utf8)! 
let decodedDictionary = try JSONDecoder().decode(Dictionary<String, User>.self, from: data) 
print(decodedDictionary) // ["user": __lldb_expr_48.User(name: "John", familyName: "Johnson")] 

let encodedData = try JSONEncoder().encode(decodedDictionary["user"]!) 
let encodedStr = String(data: encodedData, encoding: .utf8) 
print(encodedStr!) // {"name":"John","familyName":"Johnson"} 
+0

良い回答ありがとうございます。私は計算されたプロパティの方法と一緒に行くことにしました。 –