【问题标题】:Mapping a JSON object to a Swift class/struct将 JSON 对象映射到 Swift 类/结构
【发布时间】:2015-06-27 06:47:13
【问题描述】:

我需要以 JSON 格式“复制”从远程 Web API 服务返回的条目。它看起来像这样:

{
  "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 并同时创建它的变量?

像这样:

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

【问题讨论】:

    标签: json swift


    【解决方案1】:

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

    【讨论】:

    • 并在本地创建?
    【解决方案2】:

    看看这个非常适合你需要的很棒的库,Argo on GitHub

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

    【讨论】:

    • 我不想使用任何第三方库。
    【解决方案3】:

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

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

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

    结构实例总是按值传递,而类 实例总是通过引用传递。这意味着他们是 适合不同类型的任务。当你考虑数据 项目所需的结构和功能,决定 每个数据结构应该定义为一个类还是一个 结构。

    作为一般准则,考虑创建一个结构,当一个或多个 以下条件适用:

    • 结构的主要目的是封装一些相对简单的数据值。
    • 当您分配或传递一个 该结构的实例。
    • 结构存储的任何属性本身都是值类型,也应该被复制而不是引用。
    • 结构不需要继承其他现有类型的属性或行为。

    结构的良好候选示例包括:

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

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

    希望对你有所帮助。

    【讨论】:

    • 问题不在于如何解析json。
    【解决方案4】:

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

    结构动物:HandyJSON { 变量名称:字符串? 变量 id:字符串? 变量编号:整数? } 让 jsonString = "{\"name\":\"cat\",\"id\":\"12345\",\"num\":180}" 如果让动物 = JSONDeserializer.deserializeFrom(json: jsonString) { 打印(动物) }

    https://github.com/alibaba/handyjson

    【讨论】:

      【解决方案5】:

      详情

      • 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?
      }
      

      【讨论】:

      • 一个非常详细的答案 :) 另一方面,你如何使用这些模型对象来更新 UIViews?您是否还操纵模型对象内部的数据并将其传递给视图控制器?
      • 我使用 viper 架构模式(面向协议的编程)。所以我有数据层,在那里我准备、加载和保存数据。然后我将这个对象注入(阅读依赖注入和 pod 台风)到视图控制器和完整视图中。每个视图只有属性和视觉功能(改变颜色,初始化角..)。就是这样)
      【解决方案6】:

      您可以为 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)
                      }
              }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-12-24
        • 1970-01-01
        • 2018-08-18
        • 2019-05-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-04-23
        相关资源
        最近更新 更多