2017-10-26 11 views
0

私はこれが他の質問でカバーされていることを知っていますが、私はそれらに続き、私はまだ困惑しています。 JSONの構造は次のとおりです。Swift 4 JSON Decoder

 { 
     "FindBoatResult": { 
     "num_boats": 10, 
     "boat": [ 
     { 
      "num_segments": 1, 
      "segments": [ 
       { 
       "ident": "String", 
       "origin" : { 
         "code" : "String" 
       }, 
      }, 
     ] 
     } 

などですが、それは構造のように深くなります。各JSONレスポンスに複数の "セグメント"が返されます。 Swiftにはこのコードがあります。

struct Result : Decodable { 
    let FindBoatResult : FindBoatResult 
} 
struct FindBoatResult : Decodable { 
    let boats : Boats 
    let num_boats : Int 
} 
struct Boats : Decodable { 
    let segments : [Segments] 
} 
struct Segments : Decodable { 
    let ident : String? 
    let origin : Origin 
} 
struct Origin : Decodable { 
    let code : String 
} 

func getBoats() { 

let urlString = "http://myApi" 
guard let url = URL(string: urlString) else { return } 

    URLSession.shared.dataTask(with: url) { (data, response, err) in 
     guard let data = data else {return} 
     let dataAsString = String(data: data, encoding: .utf8) 
     //print(dataAsString) 

     do { 
      let boats = try 
       JSONDecoder().decode(FindBoatResult.self, from: data) 

      print(boats) 
     } catch { 
      print(err) 
     } 
    }.resume() 
} 

これは失敗し、エラーが発生しましたが、エラーが発生しました。何も表示されません。 dataAsStringはJSONを期待どおりに出力します。したがって、「データ」は良好です。

+2

エラーを 'print(error)' –

+0

...として出力するか、 'dataTask'で渡されたエラーの混乱を避けるために、一意の名前を付けます。 'do {...} catchは、parseError {print(parseError)}'をキャッチします。 – Rob

答えて

1

マイナーな問題がいくつか検出されました。これを交換してみてください:

struct FindBoatResult: Decodable { 
    let boats: Boats 
    let num_boats: Int 
} 
struct Boats: Decodable { 
    let segments: [Segments] 
} 

で:

struct FindBoatResult: Decodable { 
    let boat: [Boat] 
    let num_boats: Int 
} 
struct Boat: Decodable { 
    let segments: [Segments] 
} 

最後に、Resultタイプ(ないFindBoatResult)を使用してデコードします。ifこと

パウロの答えに拡大
JSONDecoder().decode(Result.self, from: data) 
1

が、私はさらに提案するかもしれませんプロパティ名のスウィフトコンベンションに準拠していないキーを持つJSONに悩まされています。これは、CodingKeysパターンを使用してJSONキーをベットに変換します例えば、スウィフトプロパティ名:

struct BoatResult: Decodable {   // I'd simplify this name 
    let boatCollection: BoatCollection 

    enum CodingKeys: String, CodingKey { 
     case boatCollection = "FindBoatResult" 
    } 
} 

struct BoatCollection: Decodable {  // I'd simplify this, too, removing "Find" from the name; verbs are for methods, not properties 
    let boats: [Boat] 
    let numberOfBoats: Int 

    enum CodingKeys: String, CodingKey { 
     case boats = "boat"    // "boat" isn't great property name for an array of boats, so let's map the poor JSON key to better Swift name here 
     case numberOfBoats = "num_boats" // likewise, let's map the "_" name with better camelCase property name 
    } 
} 

struct Boat: Decodable {     // This entity represents a single boat, so let's use "Boat", not "Boats" 
    let segments: [Segment] 
} 

struct Segment: Decodable {    // This entity represents a single segment, so let's use "Segment", not "Segments" 
    let identifier: String 
    let origin: Origin 

    enum CodingKeys: String, CodingKey { 
     case identifier = "ident"  // `ident` isn't a common name for identifier, so let's use something more logical 
     case origin 
    } 
} 

struct Origin: Decodable { 
    let code: String 
} 

などです。 boats)を使用し、CodingKeysを使用して、誤ったboat JSONキーをこのより良い名前のboats配列参照にマップします。またはnum_boatsのようなキーがある場合、Swiftプロパティでその悪い名前を使用して、numberOfBoats(またはcountなど)のようなものを使用し、非常に不快な構文を失うように感じないでください。

あなたがJSONのデザインをコントロールしている場合は、ここで不適切に選択されたキー名の一部を修正するだけで済みますが、Webサービスで_構文を使用することを決定した場合でも、 CodingKeysを使用して、SwiftオブジェクトがcamelCaseの規約に従うことを確認してください。

+0

質問を投稿できない理由がわかりません。それがS.O.問題を投稿するための別の会場を見つけることができます。それが仕事/秘密保持の問題であれば、問題を十分に匿名化してその懸念に対処してください。しかし、コメントであなたの問題を診断しようとするのは適切な場所ではありません。上記のコメントを削除する必要があります。 – Rob