Swift 4デコード可能なプロトコルでJSON辞書のタイプを使用してプロパティをデコードする方法


103

顧客オブジェクトにJSON辞書を含むことができるプロパティCustomerを含むデータ型があるとしましょうmetadata

struct Customer {
  let id: String
  let email: String
  let metadata: [String: Any]
}

{  
  "object": "customer",
  "id": "4yq6txdpfadhbaqnwp3",
  "email": "john.doe@example.com",
  "metadata": {
    "link_id": "linked-id",
    "buy_count": 4
  }
}

metadataプロパティには、任意のJSONマップオブジェクトにすることができます。

逆シリアル化されたJSONからプロパティをキャストする前にNSJSONDeserialization、新しいSwift 4 Decodableプロトコルを使用しても、それを行う方法を考えることができません。

DecodableプロトコルでSwift 4でこれを達成する方法を誰かが知っていますか?

回答:


88

私が見つけたこの要旨からいくつかのインスピレーションを得て、UnkeyedDecodingContainerおよびの拡張機能をいくつか作成しましたKeyedDecodingContainerここに私の要点へのリンクがあります。このコードを使用することで、任意のコードArray<Any>またはDictionary<String, Any>使い慣れた構文をデコードできます。

let dictionary: [String: Any] = try container.decode([String: Any].self, forKey: key)

または

let array: [Any] = try container.decode([Any].self, forKey: key)

編集:辞書[[String: Any]]の配列をデコードしていることに気づいた警告が1つあります。必要な構文は次のとおりです。強制キャストの代わりにエラーをスローしたいと思うでしょう:

let items: [[String: Any]] = try container.decode(Array<Any>.self, forKey: .items) as! [[String: Any]]

編集2:単にファイル全体を辞書に変換したい場合は、JSONDecoder自体を拡張して辞書を直接デコードする方法を理解していないため、JSONSerializationのAPIを使用する方がよいでしょう。

guard let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else {
  // appropriate error handling
  return
}

拡張機能

// Inspired by https://gist.github.com/mbuchetics/c9bc6c22033014aa0c550d3b4324411a

struct JSONCodingKeys: CodingKey {
    var stringValue: String

    init?(stringValue: String) {
        self.stringValue = stringValue
    }

    var intValue: Int?

    init?(intValue: Int) {
        self.init(stringValue: "\(intValue)")
        self.intValue = intValue
    }
}


extension KeyedDecodingContainer {

    func decode(_ type: Dictionary<String, Any>.Type, forKey key: K) throws -> Dictionary<String, Any> {
        let container = try self.nestedContainer(keyedBy: JSONCodingKeys.self, forKey: key)
        return try container.decode(type)
    }

    func decodeIfPresent(_ type: Dictionary<String, Any>.Type, forKey key: K) throws -> Dictionary<String, Any>? {
        guard contains(key) else { 
            return nil
        }
        guard try decodeNil(forKey: key) == false else { 
            return nil 
        }
        return try decode(type, forKey: key)
    }

    func decode(_ type: Array<Any>.Type, forKey key: K) throws -> Array<Any> {
        var container = try self.nestedUnkeyedContainer(forKey: key)
        return try container.decode(type)
    }

    func decodeIfPresent(_ type: Array<Any>.Type, forKey key: K) throws -> Array<Any>? {
        guard contains(key) else {
            return nil
        }
        guard try decodeNil(forKey: key) == false else { 
            return nil 
        }
        return try decode(type, forKey: key)
    }

    func decode(_ type: Dictionary<String, Any>.Type) throws -> Dictionary<String, Any> {
        var dictionary = Dictionary<String, Any>()

        for key in allKeys {
            if let boolValue = try? decode(Bool.self, forKey: key) {
                dictionary[key.stringValue] = boolValue
            } else if let stringValue = try? decode(String.self, forKey: key) {
                dictionary[key.stringValue] = stringValue
            } else if let intValue = try? decode(Int.self, forKey: key) {
                dictionary[key.stringValue] = intValue
            } else if let doubleValue = try? decode(Double.self, forKey: key) {
                dictionary[key.stringValue] = doubleValue
            } else if let nestedDictionary = try? decode(Dictionary<String, Any>.self, forKey: key) {
                dictionary[key.stringValue] = nestedDictionary
            } else if let nestedArray = try? decode(Array<Any>.self, forKey: key) {
                dictionary[key.stringValue] = nestedArray
            }
        }
        return dictionary
    }
}

extension UnkeyedDecodingContainer {

    mutating func decode(_ type: Array<Any>.Type) throws -> Array<Any> {
        var array: [Any] = []
        while isAtEnd == false {
            // See if the current value in the JSON array is `null` first and prevent infite recursion with nested arrays.
            if try decodeNil() {
                continue
            } else if let value = try? decode(Bool.self) {
                array.append(value)
            } else if let value = try? decode(Double.self) {
                array.append(value)
            } else if let value = try? decode(String.self) {
                array.append(value)
            } else if let nestedDictionary = try? decode(Dictionary<String, Any>.self) {
                array.append(nestedDictionary)
            } else if let nestedArray = try? decode(Array<Any>.self) {
                array.append(nestedArray)
            }
        }
        return array
    }

    mutating func decode(_ type: Dictionary<String, Any>.Type) throws -> Dictionary<String, Any> {

        let nestedContainer = try self.nestedContainer(keyedBy: JSONCodingKeys.self)
        return try nestedContainer.decode(type)
    }
}

興味深いことに、私はこの要旨を試し、結果を@loudmouthに更新します
Pitiphong Phongpattranont

@PitiphongPhongpattranontこのコードはうまくいきましたか?
ラウドマス2017

1
@JonBrooksは中で最後の条件UnkeyedDecodingContainerのをdecode(_ type: Array<Any>.Type) throws -> Array<Any>をチェックして、ネストされた配列。したがって、次のようなデータ構造がある場合:[true, 452.0, ["a", "b", "c"] ] ネストされた["a", "b", "c"]配列をプルします。decode方法UnkeyedDecodingContainerコンテナから要素オフ「ポップ」。それは無限の再帰を引き起こすべきではありません。
ラウドマス

1
@loudmouthでは、jsonのキーにnil値を含めることができます{"array": null}。したがって、guard contains(key)パスはしますが、キー「配列」のnull値をデコードしようとすると、数行後にクラッシュします。したがって、を呼び出す前に、値が実際にnullでないかどうかを確認するための条件をもう1つ追加することをお勧めしますdecode
chebur

2
解決策を見つけました:} else if let nestedArray = try? decode(Array<Any>.self, forKey: key)試してみる代わりに:} else if var nestedContainer = try? nestedUnkeyedContainer(), let nestedArray = try? nestedContainer.decode(Array<Any>.self) {
Jon Brooks

23

私もこの問題で遊んだことがあり、最後に「汎用JSON」タイプを処理するための単純なライブラリを作成しました。(「汎用」とは、「構造が事前にわかっていない」ことを意味します。)主なポイントは、具象型で汎用JSONを表すことです。

public enum JSON {
    case string(String)
    case number(Float)
    case object([String:JSON])
    case array([JSON])
    case bool(Bool)
    case null
}

このタイプは、Codableおよびを実装できEquatableます。


13

Decodableプロトコルを確認するメタデータ構造体を作成し、JSONDecoderクラスを使用して、以下のようなデコードメソッドを使用してデータからオブジェクトを作成できます。

let json: [String: Any] = [
    "object": "customer",
    "id": "4yq6txdpfadhbaqnwp3",
    "email": "john.doe@example.com",
    "metadata": [
        "link_id": "linked-id",
        "buy_count": 4
    ]
]

struct Customer: Decodable {
    let object: String
    let id: String
    let email: String
    let metadata: Metadata
}

struct Metadata: Decodable {
    let link_id: String
    let buy_count: Int
}

let data = try JSONSerialization.data(withJSONObject: json, options: .prettyPrinted)

let decoder = JSONDecoder()
do {
    let customer = try decoder.decode(Customer.self, from: data)
    print(customer)
} catch {
    print(error.localizedDescription)
}

10
metadata値の構造がわからないので、できません。任意のオブジェクトにすることができます。
Pitiphong Phongpattranont 2017年

配列型または辞書型のどちらでもかまいませんか?
Suhit Patil 2017

メタデータの構造について例を挙げたり、説明を追加したりできますか
Suhit Patil

2
の値は、metadata任意のJSONオブジェクトにすることができます。したがって、空の辞書または任意の辞書にすることができます。"metadata":{} "metadata":{user_id: "id"} "metadata":{preference:{shows_value:true、language: "en"}}など
Pitiphong Phongpattranont

1つの可能なオプションは、メタデータ構造体のすべてのパラメーターをオプションとして使用し、構造体メタデータ{var user_id:String?変数設定:文字列?}
Suhit Patil 2017

8

私は少し違う解決策を思いついた。

[String: Any]解析するのが単純な以上のものがあるとしましょう。Anyは、配列、ネストされた辞書、または配列の辞書である可能性があります。

このようなもの:

var json = """
{
  "id": 12345,
  "name": "Giuseppe",
  "last_name": "Lanza",
  "age": 31,
  "happy": true,
  "rate": 1.5,
  "classes": ["maths", "phisics"],
  "dogs": [
    {
      "name": "Gala",
      "age": 1
    }, {
      "name": "Aria",
      "age": 3
    }
  ]
}
"""

まあ、これは私の解決策です:

public struct AnyDecodable: Decodable {
  public var value: Any

  private struct CodingKeys: CodingKey {
    var stringValue: String
    var intValue: Int?
    init?(intValue: Int) {
      self.stringValue = "\(intValue)"
      self.intValue = intValue
    }
    init?(stringValue: String) { self.stringValue = stringValue }
  }

  public init(from decoder: Decoder) throws {
    if let container = try? decoder.container(keyedBy: CodingKeys.self) {
      var result = [String: Any]()
      try container.allKeys.forEach { (key) throws in
        result[key.stringValue] = try container.decode(AnyDecodable.self, forKey: key).value
      }
      value = result
    } else if var container = try? decoder.unkeyedContainer() {
      var result = [Any]()
      while !container.isAtEnd {
        result.append(try container.decode(AnyDecodable.self).value)
      }
      value = result
    } else if let container = try? decoder.singleValueContainer() {
      if let intVal = try? container.decode(Int.self) {
        value = intVal
      } else if let doubleVal = try? container.decode(Double.self) {
        value = doubleVal
      } else if let boolVal = try? container.decode(Bool.self) {
        value = boolVal
      } else if let stringVal = try? container.decode(String.self) {
        value = stringVal
      } else {
        throw DecodingError.dataCorruptedError(in: container, debugDescription: "the container contains nothing serialisable")
      }
    } else {
      throw DecodingError.dataCorrupted(DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Could not serialise"))
    }
  }
}

使ってみてください

let stud = try! JSONDecoder().decode(AnyDecodable.self, from: jsonData).value as! [String: Any]
print(stud)

6

古い答えを見つけたとき、私は単純なJSONオブジェクトのケースのみをテストしましたが、@ slurmomaticや@zoulのようなランタイム例外が発生する空のケースは見つかりませんでした。この問題でごめんなさい。

そこで、単純なJSONValueプロトコルAnyJSONValueを使用して別の方法を試し、型消去構造体を実装して、の代わりにその型を使用しAnyます。ここに実装があります。

public protocol JSONType: Decodable {
    var jsonValue: Any { get }
}

extension Int: JSONType {
    public var jsonValue: Any { return self }
}
extension String: JSONType {
    public var jsonValue: Any { return self }
}
extension Double: JSONType {
    public var jsonValue: Any { return self }
}
extension Bool: JSONType {
    public var jsonValue: Any { return self }
}

public struct AnyJSONType: JSONType {
    public let jsonValue: Any

    public init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()

        if let intValue = try? container.decode(Int.self) {
            jsonValue = intValue
        } else if let stringValue = try? container.decode(String.self) {
            jsonValue = stringValue
        } else if let boolValue = try? container.decode(Bool.self) {
            jsonValue = boolValue
        } else if let doubleValue = try? container.decode(Double.self) {
            jsonValue = doubleValue
        } else if let doubleValue = try? container.decode(Array<AnyJSONType>.self) {
            jsonValue = doubleValue
        } else if let doubleValue = try? container.decode(Dictionary<String, AnyJSONType>.self) {
            jsonValue = doubleValue
        } else {
            throw DecodingError.typeMismatch(JSONType.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Unsupported JSON tyep"))
        }
    }
}

そして、これはデコード時にそれを使用する方法です

metadata = try container.decode ([String: AnyJSONValue].self, forKey: .metadata)

この問題の問題は、を呼び出さなければならないことvalue.jsonValue as? Intです。私たちConditional ConformanceはSwiftに着陸するまで待つ必要があります。それでこの問題が解決するか、少なくともそれがより良くなるのに役立ちます。


[古い答え]

私はこの質問をApple Developerフォーラムに投稿しましたが、とても簡単であることがわかりました。

できます

metadata = try container.decode ([String: Any].self, forKey: .metadata)

イニシャライザ内。

そもそもそれを見逃してしまったのは私の悪かった。


4
質問へのリンクをApple Developerに投稿できます。Anyは準拠しDecodableていないので、これが正しい答えかどうかはわかりません。
Reza Shirazian 2017

@RezaShirazianそもそもそう思っていました。しかし、キーがHashableに準拠し、その値に依存しない場合、DictionaryはEncodableに準拠していることがわかります。辞書ヘッダーを開いて、自分で確認できます。拡張ディクショナリ:Encodable where Key:Hashable拡張ディクショナリ:Decodable where Key:Hashable forums.developer.apple.com/thread/80288#237680
Pitiphong Phongpattranont

6
現在、これは機能しません。「Dictionary <String、Any>はDecodableに準拠していません。AnyはDecodableに準拠していないためです」
mbuchetics

うまくいくことがわかりました。コードで使用しています。「ディクショナリをDecodableプロトコルに準拠させるためには、Dictionaryの値がDecodableプロトコルに準拠する必要がある」という要件を表現する方法がないことを理解する必要があります。これは、Swift 4にはまだ実装されていない「条件付きの適合性」です。SwiftType System(およびGenerics)には多くの制限があるため、今のところ問題ないと思います。したがって、これは今のところ機能しますが、Swift Type Systemが将来改善される場合(特に条件付き適合性が実装される場合)、これは機能しないはずです。
Pitiphong Phongpattranont 2017

3
Xcode 9ベータ5以降、私には機能しません。コンパイルは実行時に行われます。AnyはDecodableに準拠していないため、Dictionary <String、Any>はDecodableに準拠していません。
zoul 2017

6

あなたが使用している場合はSwiftyJSONを JSONを解析するために、あなたはに更新できる4.1.0があるCodableプロトコルのサポート。宣言するだけでmetadata: JSON準備完了です。

import SwiftyJSON

struct Customer {
  let id: String
  let email: String
  let metadata: JSON
}

なぜこの回答が反対投票されたのかはわかりません。それは完全に有効であり、問​​題を解決します。
Leonid Usov 2018

SwiftyJSONから復号可能への移行のために良いことのようです
のMichałZiobro

これは、元の問題であったメタデータjsonを解析する方法を解決しません。
ラマコーン

1

BeyovaJSONを見てください。

import BeyovaJSON

struct Customer: Codable {
  let id: String
  let email: String
  let metadata: JToken
}

//create a customer instance

customer.metadata = ["link_id": "linked-id","buy_count": 4]

let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted 
print(String(bytes: try! encoder.encode(customer), encoding: .utf8)!)

ああ、本当にいい。これを使用して、JSONとして汎用JSONを受け取り、いくつかの値を追加してサーバーに返します。とても良いです。それはあなたがやった素晴らしい仕事です:)
Vitor Hugo Schwaab 2018

1

最も簡単で推奨される方法は、JSONの辞書またはモデルごとに個別のモデル作成することです

これが私がすることです

//Model for dictionary **Metadata**

struct Metadata: Codable {
    var link_id: String?
    var buy_count: Int?
}  

//Model for dictionary **Customer**

struct Customer: Codable {
   var object: String?
   var id: String?
   var email: String?
   var metadata: Metadata?
}

//Here is our decodable parser that decodes JSON into expected model

struct CustomerParser {
    var customer: Customer?
}

extension CustomerParser: Decodable {

//keys that matches exactly with JSON
enum CustomerKeys: String, CodingKey {
    case object = "object"
    case id = "id"
    case email = "email"
    case metadata = "metadata"
}

init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CustomerKeys.self) // defining our (keyed) container

    let object: String = try container.decode(String.self, forKey: .object) // extracting the data
    let id: String = try container.decode(String.self, forKey: .id) // extracting the data
    let email: String = try container.decode(String.self, forKey: .email) // extracting the data

   //Here I have used metadata model instead of dictionary [String: Any]
    let metadata: Metadata = try container.decode(Metadata.self, forKey: .metadata) // extracting the data

    self.init(customer: Customer(object: object, id: id, email: email, metadata: metadata))

    }
}

使用法:

  if let url = Bundle.main.url(forResource: "customer-json-file", withExtension: "json") {
        do {
            let jsonData: Data =  try Data(contentsOf: url)
            let parser: CustomerParser = try JSONDecoder().decode(CustomerParser.self, from: jsonData)
            print(parser.customer ?? "null")

        } catch {

        }
    }

**解析中に安全のためにオプションを使用しましたが、必要に応じて変更できます。

このトピックの詳細を読む


1
あなたの答えは確かにSwift 4.1に適切なものであり、あなたの投稿の最初の行は完全に終わっています!データがWebサービスからのものであると想定します。単純なネストされたオブジェクトをモデル化してから、ドット構文を使用してそれぞれを取得できます。以下のsuhitの回答を参照してください。
David H

1

私は、復号化が+エンコードする方法を容易にするためのポッドをしました[String: Any][Any]。そして、これはオプションのプロパティをエンコードまたはデコードします。ここではhttps://github.com/levantAJ/AnyCodable

pod 'DynamicCodable', '1.0'

どうやって使うのですか:

import DynamicCodable

struct YourObject: Codable {
    var dict: [String: Any]
    var array: [Any]
    var optionalDict: [String: Any]?
    var optionalArray: [Any]?

    enum CodingKeys: String, CodingKey {
        case dict
        case array
        case optionalDict
        case optionalArray
    }

    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        dict = try values.decode([String: Any].self, forKey: .dict)
        array = try values.decode([Any].self, forKey: .array)
        optionalDict = try values.decodeIfPresent([String: Any].self, forKey: .optionalDict)
        optionalArray = try values.decodeIfPresent([Any].self, forKey: .optionalArray)
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        try container.encode(dict, forKey: .dict)
        try container.encode(array, forKey: .array)
        try container.encodeIfPresent(optionalDict, forKey: .optionalDict)
        try container.encodeIfPresent(optionalArray, forKey: .optionalArray)
    }
}

0

@loudmouthの回答に触発された[String: Any]、より一般的な(だけでなく、[Any]デコードできる)およびカプセル化されたアプローチ(個別のエンティティが使用されます)です。

使用方法は次のようになります。

extension Customer: Decodable {
  public init(from decoder: Decoder) throws {
    let selfContainer = try decoder.container(keyedBy: CodingKeys.self)
    id = try selfContainer.decode(.id)
    email = try selfContainer.decode(.email)
    let metadataContainer: JsonContainer = try selfContainer.decode(.metadata)
    guard let metadata = metadataContainer.value as? [String: Any] else {
      let context = DecodingError.Context(codingPath: [CodingKeys.metadata], debugDescription: "Expected '[String: Any]' for 'metadata' key")
      throw DecodingError.typeMismatch([String: Any].self, context)
    }
    self.metadata = metadata
  }

  private enum CodingKeys: String, CodingKey {
    case id, email, metadata
  }
}

JsonContainerは、拡張せずにJSONデータをJSONオブジェクト(配列または辞書)にラップするために使用するヘルパーエンティティです*DecodingContainer(JSONオブジェクトがで意図されていないまれなケースを妨げることはありません[String: Any])。

struct JsonContainer {

  let value: Any
}

extension JsonContainer: Decodable {

  public init(from decoder: Decoder) throws {
    if let keyedContainer = try? decoder.container(keyedBy: Key.self) {
      var dictionary = [String: Any]()
      for key in keyedContainer.allKeys {
        if let value = try? keyedContainer.decode(Bool.self, forKey: key) {
          // Wrapping numeric and boolean types in `NSNumber` is important, so `as? Int64` or `as? Float` casts will work
          dictionary[key.stringValue] = NSNumber(value: value)
        } else if let value = try? keyedContainer.decode(Int64.self, forKey: key) {
          dictionary[key.stringValue] = NSNumber(value: value)
        } else if let value = try? keyedContainer.decode(Double.self, forKey: key) {
          dictionary[key.stringValue] = NSNumber(value: value)
        } else if let value = try? keyedContainer.decode(String.self, forKey: key) {
          dictionary[key.stringValue] = value
        } else if (try? keyedContainer.decodeNil(forKey: key)) ?? false {
          // NOP
        } else if let value = try? keyedContainer.decode(JsonContainer.self, forKey: key) {
          dictionary[key.stringValue] = value.value
        } else {
          throw DecodingError.dataCorruptedError(forKey: key, in: keyedContainer, debugDescription: "Unexpected value for \(key.stringValue) key")
        }
      }
      value = dictionary
    } else if var unkeyedContainer = try? decoder.unkeyedContainer() {
      var array = [Any]()
      while !unkeyedContainer.isAtEnd {
        let container = try unkeyedContainer.decode(JsonContainer.self)
        array.append(container.value)
      }
      value = array
    } else if let singleValueContainer = try? decoder.singleValueContainer() {
      if let value = try? singleValueContainer.decode(Bool.self) {
        self.value = NSNumber(value: value)
      } else if let value = try? singleValueContainer.decode(Int64.self) {
        self.value = NSNumber(value: value)
      } else if let value = try? singleValueContainer.decode(Double.self) {
        self.value = NSNumber(value: value)
      } else if let value = try? singleValueContainer.decode(String.self) {
        self.value = value
      } else if singleValueContainer.decodeNil() {
        value = NSNull()
      } else {
        throw DecodingError.dataCorruptedError(in: singleValueContainer, debugDescription: "Unexpected value")
      }
    } else {
      let context = DecodingError.Context(codingPath: [], debugDescription: "Invalid data format for JSON")
      throw DecodingError.dataCorrupted(context)
    }
  }

  private struct Key: CodingKey {
    var stringValue: String

    init?(stringValue: String) {
      self.stringValue = stringValue
    }

    var intValue: Int?

    init?(intValue: Int) {
      self.init(stringValue: "\(intValue)")
      self.intValue = intValue
    }
  }
}

数値型とブール型はによって裏付けられていることに注意してくださいNSNumber。そうでなければ、次のようなものは機能しません。

if customer.metadata["keyForInt"] as? Int64 { // as it always will be nil

autoDecodingで十分な15個のプロパティと、いくつかのカスタムデコード処理が必要な3個のプロパティがあるため、選択したプロパティのみをデコードし、他のプロパティは自動的にデコードしたままにできますか?
のMichałZiobro

@MichałZiobroデータの一部をJSONオブジェクトにデコードし、その一部を個別のインスタンス変数にデコードしますか?または、オブジェクトの一部のためだけに部分的なデコード初期化子を書くことについて質問しています(そして、JSONのような構造との共通点はありません)?私の知る限りでは、最初の質問に対する答えは「はい」であり、2番目の質問に対する答えは「いいえ」です。
アレクセイコジェフニコフ2018

私は、カスタマイズされたデコーディングおよび標準のデフォルトデコードすると、残りの唯一のいくつかのプロパティがしたい
のMichałZiobro

@MichałZiobro私があなたを正しく理解しているなら、それは不可能です。とにかく、あなたの質問は現在のSOの質問には関係がなく、別の質問の価値があります。
Alexey Kozhevnikov

0

デコーダとコーディングキーを使用してデコードする

public let dataToDecode: [String: AnyDecodable]

enum CodingKeys: CodingKey {
    case dataToDecode
}

init(from decoder: Decoder) throws {
    let container = try decoder.container(keyedBy: CodingKeys.self)
    self.dataToDecode = try container.decode(Dictionary<String, AnyDecodable>.self, forKey: .dataToDecode) 
}    

-1
extension ViewController {

    func swiftyJson(){
        let url = URL(string: "https://itunes.apple.com/search?term=jack+johnson")
        //let url = URL(string: "http://makani.bitstaging.in/api/business/businesses_list")

        Alamofire.request(url!, method: .get, parameters: nil).responseJSON { response in
            var arrayIndexes = [IndexPath]()
            switch(response.result) {
            case .success(_):

                let data = response.result.value as! [String : Any]

                if let responseData =  Mapper<DataModel>().map(JSON: data) {
                    if responseData.results!.count > 0{
                        self.arrayExploreStylistList = []
                    }
                    for i in 0..<responseData.results!.count{
                        arrayIndexes.append(IndexPath(row: self.arrayExploreStylistList.count + i, section: 0))
                    }
                    self.arrayExploreStylistList.append(contentsOf: responseData.results!)

                    print(arrayIndexes.count)

                }

                //                    if let arrNew = data["results"] as? [[String : Any]]{
                //                        let jobData = Mapper<DataModel>().mapArray(JSONArray: arrNew)
                //                        print(jobData)
                //                        self.datamodel = jobData
                //                    }
                self.tblView.reloadData()
                break

            case .failure(_):
                print(response.result.error as Any)
                break

            }
        }

    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.