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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29749652/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 17:51:35  来源:igfitidea点击:

Mapping a JSON object to a Swift class/struct

jsonswift

提问by Victor Sigler

I need to "replicate" an entiry which is returned from a remote web API service in JSON. It looks like this:

我需要“复制”从 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"
  }
}

Here's my attempt:

这是我的尝试:

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. Is it a good idea to use structs instead of classes for such a goal as mine?
  2. Can I anyhow define a nested struct or a class, say Details1 and create a variable of it at the same time?
  1. 对于我这样的目标,使用结构而不是类是个好主意吗?
  2. 无论如何,我可以定义一个嵌套的结构或类,比如 Details1 并同时创建它的变量吗?

Like this:

像这样:

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

回答by Victor Sigler

You can use any if the following good open-source libraries available to handle the mapping of JSON to Object in Swift, take a look :

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

Each one have nice a good tutorial for beginners.

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

Regarding the theme of structor class, you can consider the following text from The Swift Programming Languagedocumentation:

关于struct或的主题class,您可以参考The Swift Programming Language文档中的以下文本:

Structure instances are always passed by value, and class instances are always passed by reference. This means that they are suited to different kinds of tasks. As you consider the data constructs and functionality that you need for a project, decide whether each data construct should be defined as a class or as a structure.

As a general guideline, consider creating a structure when one or more of these conditions apply:

  • The structure's primary purpose is to encapsulate a few relatively simple data values.
  • It is reasonable to expect that the encapsulated values will be copied rather than referenced when you assign or pass around an instance of that structure.
  • Any properties stored by the structure are themselves value types, which would also be expected to be copied rather than referenced.
  • The structure does not need to inherit properties or behavior from another existing type.

Examples of good candidates for structures include:

  • The size of a geometric shape, perhaps encapsulating a width property and a height property, both of type Double.
  • A way to refer to ranges within a series, perhaps encapsulating a start property and a length property, both of type Int.
  • A point in a 3D coordinate system, perhaps encapsulating x, y and z properties, each of type Double.

In all other cases, define a class, and create instances of that class to be managed and passed by reference. In practice, this means that most custom data constructs should be classes, not structures.

结构实例总是按值传递,类实例总是按引用传递。这意味着它们适用于不同类型的任务。当您考虑项目所需的数据构造和功能时,决定每个数据构造应定义为类还是结构。

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

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

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

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

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

I hope this help you.

我希望这对你有帮助。

回答by henshao

HandyJSONis exactly what you need. See code example:

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

https://github.com/alibaba/handyjson

回答by Vasily Bodnarchuk

Details

细节

  • Xcode 10.2.1 (10E1001), Swift 5
  • Xcode 10.2.1 (10E1001),Swift 5

Links

链接

Pods:

豆荚:

More info:

更多信息:

Task

任务

Get itunes search results using iTunes Search APIwith simple request https://itunes.apple.com/search?term=Hyman+johnson

使用iTunes Search API通过简单请求获取 iTunes 搜索结果https://itunes.apple.com/search?term=Hyman+johnson

Full sample

完整样品

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=Hyman+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?
}

回答by Sua Le

You can go with this extension for Alamofire https://github.com/sua8051/AlamofireMapper

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

Declare a class or struct:

声明一个类或结构:

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!
}

Use:

用:

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)
                }
        }

回答by bLacK hoLE

you could use SwiftyJson and let json = JSONValue(dataFromNetworking) if let userName = json[0]["user"]["name"].string{ //Now you got your value }

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

回答by sweepy_

Take a look at this awesome library that perfectly fits your need, Argo on GitHub.

看看这个非常适合您需求的很棒的库,GitHub 上的 Argo

In your case, a struct is ok. You can read more on how to choose between a struct and a class here.

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