测试测试通过 | ✓ |
语言编程语言 | SwiftSwift |
许可证 | MIT |
发布最新发布 | 2016年11月 |
SwiftSwift 版本 | 3.0 |
SPM支持 SPM | ✗ |
由Matthew Cheok和Nadohs维护。
Swift 中轻松进行 JSON 编码和解码
carthage update
github "matthewcheok/JSONCodable" ~> 3.0
Podfile
并运行 pod install
pod 'JSONCodable', '~> 3.0'
或将其作为 Git 子模块克隆,
或只需将 JSONCodable 文件夹中的文件复制到您的项目中。
TLDR
let
属性enum
属性变更日志
JSONCodable 由两个独立的协议 JSONEncodable
和 JSONDecodable
组成。
JSONEncodable
允许您的结构和类生成 NSDictionary
或 [String: AnyObject]
等价物,用于与 NSJSONSerialization
一起使用。
JSONDecodable
允许您从包含网络请求等内容的 NSDictionary
生成结构。
以这些两个类型为例
struct User {
let id: Int
let name: String
var email: String?
var company: Company?
var friends: [User] = []
}
struct Company {
let name: String
var address: String?
}
只需将符合性添加到 JSONDecodable
(或到 JSONCodable
)即可
extension User: JSONDecodable {
init(object: JSONObject) throws {
let decoder = JSONDecoder(object: object)
id = try decoder.decode("id")
name = try decoder.decode("full_name")
email = try decoder.decode("email")
company = try decoder.decode("company")
friends = try decoder.decode("friends")
}
}
extension Company: JSONDecodable {
init(object: JSONObject) throws {
let decoder = JSONDecoder(object: object)
name = try decoder.decode("name")
address = try decoder.decode("address")
}
}
关于类扩展的说明:在 Swift 2.2 更新后,不再支持在扩展中添加类初始化器。对此的当前建议的解决方案是在类定义中添加初始化器。对于结构,扩展仍然有效,因为它们在此情况下已经如此。
然后为 init(object: JSONObject)
提供JSONObject
是 [String:AnyObject]
的别名的实现。像之前一样,您可以使用此功能来配置字典中的键与您的结构和类属性之间的映射。
let user = try User(object: JSON)
print("\(user)")
结果
User(
id: 24,
name: "John Appleseed",
email: Optional("[email protected]"),
company: Optional(Company(
name: "Apple",
address: Optional("1 Infinite Loop, Cupertino, CA")
)),
friends: [
User(
id: 27,
name: "Bob Jefferson",
email: nil,
company: nil,
friends: []
),
User(
id: 29,
name: "Jen Jackson",
email: nil,
company: nil,
friends: []
)
]
)
解码还支持使用 .
分隔符获取字典中的值,对于数组使用 [index]
。以下是一个示例
name = try decoder.decode("value[0].properties.name")
只需添加符合性到 JSONEncodable
(或到 JSONCodable
)。
extension User: JSONEncodable {
func toJSON() throws -> AnyObject {
return try JSONEncoder.create({ (encoder) -> Void in
try encoder.encode(id, key: "id")
try encoder.encode(name, key: "full_name")
try encoder.encode(email, key: "email")
try encoder.encode(company, key: "company")
try encoder.encode(friends, key: "friends")
})
}
}
extension Company: JSONEncodable {}
func toJSON()
的默认实现使用反射检查您类型的属性(请参阅Company
。)如果您需要不同的映射,可以提供您自己的实现(请参阅User
。)
创建您的结构体实例后,使用func toJSON()
方法来获取适合与NSJSONSerialization
一起使用的等效形式
let dict = try user.toJSON()
print("dict: \(dict)")
结果
[full_name: John Appleseed, id: 24, email: john@appleseed.com, company: {
address = "1 Infinite Loop, Cupertino, CA";
name = Apple;
}, friends: (
{
friends = (
);
"full_name" = "Bob Jefferson";
id = 27;
},
{
friends = (
);
"full_name" = "Jen Jackson";
id = 29;
}
)]
在JSONDecodable
上提供了便利的初始化器init?(JSONString: String)
。您还可以使用func toJSONString() throws -> String
来获取您类型的字符串等效形式。
要转换值,创建一个JSONTransformer
实例
let JSONTransformerStringToNSURL = JSONTransformer<String, NSURL>(
decoding: {NSURL(string: $0)},
encoding: {$0.absoluteString})
JSONTransformer
在两种类型之间转换,在这种情况下是String
和NSURL
。它需要一个用于解码的闭包和一个用于编码的闭包,在每种情况下,给定输入类型,您都返回相应类型的可选值(如果转换不可行,您可以返回nil
)。
接下来,使用func encode()
和func decode()
的重载版本来提供转换器
struct User {
...
var website: NSURL?
}
init(object: JSONObject) throws {
...
website = try JSONDictionary.decode("website", transformer: JSONTransformerStringToNSURL)
}
func toJSON() throws -> AnyObject {
return try JSONEncoder.create({ (encoder) -> Void in
...
try result.encode(website, key: "website", transformer: JSONTransformerStringToNSURL)
})
}
以下提供默认转换器
JSONTransformers.StringToNSURL
: String <-> NSURL
JSONTransformers.StringToNSDate
: String <-> NSDate
ISO格式随时提出建议!
这允许对JSONDecoder扩展,以便类型系统更好地在解码中提供帮助。例如,您可以这样做
extension JSONDecoder {
public func decode(key: String) throws -> NSURL {
return try decode(key, transformer: JSONTransformers.StringToNSURL)
}
}
然后您只需要做
try url = decoder.decode("url")
而不是
try url = decoder.decode("url", JSONTransformers.StringToNSURL)
有关更多详细信息,请参考工作区中包含的游乐场。
JSONCodable
遵循MIT许可。