将 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
Mapping a JSON object to a Swift class/struct
提问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
}
- Is it a good idea to use structs instead of classes for such a goal as mine?
- Can I anyhow define a nested struct or a class, say Details1 and create a variable of it at the same time?
- 对于我这样的目标,使用结构而不是类是个好主意吗?
- 无论如何,我可以定义一个嵌套的结构或类,比如 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)
}
回答by Vasily Bodnarchuk
Details
细节
- Xcode 10.2.1 (10E1001), Swift 5
- Xcode 10.2.1 (10E1001),Swift 5
Links
链接
Pods:
豆荚:
- Alamofire- loading data
- Alamofire- 加载数据
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.

