将JSON对象映射到Swift类/结构

时间:2015-04-20 13:43:29

标签: json swift

我需要“复制”从JSON中的远程Web API服务返回的entiry。它看起来像这样:

{
  "field1": "some_id",
  "entity_name" = "Entity1"
  "field2": "some name",
  "details1": [{
    "field1": 11,
    "field2": "some value",
    "data": {
      "key1": "value1",
      "key2": "value2",
      "key3": "value3",
      // any other, unknown at compile time keys
    }
  }],
  "details2": {
    "field1": 13,
    "field2": "some value2"
  }
}

这是我的尝试:

struct Entity1 {
  struct Details1 {
    let field1: UInt32
    let field2: String
    let data: [String: String]
  }

  struct Details2 {
    let field1: UInt32
    let field2: String
  }

  let field1: String
  static let entityName = "Entity1"
  let field2: String
  let details1: [Details1]
  let details2: Details2 
}
  1. 使用结构而不是类来实现这样的目标是个好主意 像我一样?
  2. 无论如何,我可以定义一个嵌套的结构或类 Details1并同时创建它的变量?
  3. 像这样:

    //doesn't compile 
    struct Entity1 {
      let details1: [Details1 { 
      let field1: UInt32
      let field2: String
      let data: [String: String]
    }]
    

6 个答案:

答案 0 :(得分:18)

如果以下优秀的开源库可用于处理Swift中JSON到Object的映射,可以使用任何一个,看看:

每个人都有一个很好的初学者教程。

关于structclass的主题,您可以考虑The Swift Programming Language文档中的以下文字:

  

结构实例总是按值和类传递   实例总是通过引用传递。这意味着他们是   适合不同类型的任务。在考虑数据时   您决定项目所需的构造和功能   是否应将每个数据结构定义为类或类   结构

     

作为一般准则,请考虑在一个或多个时创建结构   这些条件适用:

     
      
  • 该结构的主要目的是封装一些相对简单的数据值。
  •   
  • 可以合理地预期在分配或传递时,将复制封装的值而不是引用   该结构的一个例子。
  •   
  • 结构存储的任何属性本身都是值类型,也可以复制而不是引用它们。
  •   
  • 该结构不需要从另一个现有类型继承属性或行为。
  •   
     

结构的良好候选者的例子包括:

     
      
  • 几何形状的大小,可能封装了width属性和height属性,两者都是Double。
  •   
  • 一种引用系列中范围的方法,可能封装了一个类型为Int的起始属性和长度属性。
  •   
  • 3D坐标系中的一个点,可能包含x,y和z属性,每个属性为Double。
  •   
     

在所有其他情况下,定义一个类,并创建该类的实例   通过引用进行管理和传递。在实践中,这意味着   大多数自定义数据结构应该是类,而不是结构。

我希望这对你有所帮助。

答案 1 :(得分:5)

HandyJSON正是您所需要的。参见代码示例:

struct Animal: HandyJSON {
    var name: String?
    var id: String?
    var num: Int?
}

let jsonString = "{\"name\":\"cat\",\"id\":\"12345\",\"num\":180}"

if let animal = JSONDeserializer.deserializeFrom(json: jsonString) {
    print(animal)
}

https://github.com/alibaba/handyjson

答案 2 :(得分:3)

详细

  • Xcode 10.2.1(10E1001),Swift 5

链接

荚:

更多信息:

任务

使用简单请求iTunes Search API

,使用https://itunes.apple.com/search?term=jack+johnson获取itunes搜索结果

完整样本

import UIKit
import Alamofire

// Itunce api doc: https://affiliate.itunes.apple.com/resources/documentation/itunes-store-web-service-search-api/#searching

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        loadData()
    }

    private func loadData() {
        let urlString = "https://itunes.apple.com/search?term=jack+johnson"
        Alamofire.request(urlString).response { response in
            guard let data = response.data else { return }
            do {
                let decoder = JSONDecoder()
                decoder.keyDecodingStrategy = .convertFromSnakeCase
                let result = try decoder.decode(ItunceItems.self, from: data)
                print(result)
            } catch let error {
                print("\(error.localizedDescription)")
            }
        }
    }
}

struct ItunceItems: Codable {
    let resultCount: Int
    let results: [ItunceItem]
}

struct ItunceItem: Codable {
    var wrapperType: String?
    var artistId: Int?
    var trackName: String?
    var trackPrice: Double?
    var currency: String?
}

答案 3 :(得分:0)

您可以使用SwiftyJson和let json = JSONValue(dataFromNetworking) if let userName = json[0]["user"]["name"].string{ //Now you got your value }

答案 4 :(得分:0)

看看这个非常适合您需求的精彩库Argo on GitHub

在你的情况下,结构是可以的。您可以阅读有关如何在结构和类here之间进行选择的更多信息。

答案 5 :(得分:0)

您可以使用Alamofire https://github.com/sua8051/AlamofireMapper的扩展名

声明一个类或结构:

class UserResponse: Decodable {
    var page: Int!
    var per_page: Int!
    var total: Int!
    var total_pages: Int!

    var data: [User]?
}

class User: Decodable {
    var id: Double!
    var first_name: String!
    var last_name: String!
    var avatar: String!
}

使用:

import Alamofire
import AlamofireMapper

let url1 = "https://raw.githubusercontent.com/sua8051/AlamofireMapper/master/user1.json"
        Alamofire.request(url1, method: .get
            , parameters: nil, encoding: URLEncoding.default, headers: nil).responseObject { (response: DataResponse<UserResponse>) in
                switch response.result {
                case let .success(data):
                    dump(data)
                case let .failure(error):
                    dump(error)
                }
        }