测试已测试 | ✓ |
Lang语言 | SwiftSwift |
许可证 | MIT |
发布最新发布 | 2016年11月 |
SwiftSwift 版本 | 3.0 |
SPM支持 SPM | ✗ |
由 Bartek Chlebek 维护。
罗塞塔石碑是一块花岗闪长岩纪念碑,刻有公元前196年在孟菲斯颁布的法令。它为现代对埃及象形文字的理解提供了关键。 wiki
就像罗塞塔石碑使翻译埃及象形文字成为可能一样,这个库旨在使将 JSON 解析到 Swift 对象以及反向转换变得简单且安全。
Rosetta 本身在开发中,需要随 Xcode 6.3 测试版一起提供的 Swift 1.2。
克隆此仓库。将 Rosetta 项目文件添加到您的工作区。然后在目标的 构建阶段 的 目标依赖性 中添加 Rosetta-iOS
或 `Rosetta-OSX
` 框架。然后在您的代码中添加 import Rosetta
,您应该就可以运行了。
JSON
解析到 Swift 类型
(支持 类 和 结构体)JSON
(如果您可以将 JSON
解析为一个 Swift 类型
,您总能得到一个 JSON
返回)JSON
中的 Strings
可以转换为 NSURL
)这只是一个关于 Rosetta 如何工作的简要概述,但应该可以给出您大致的概念。有关详尽的文档,请参阅 指南。
使用 Rosetta
的最简单方法就是让您的类型实现 JSONConvertible
协议
struct User: JSONConvertible {
var ID: String?
var name: String?
var age: Int?
var website: NSURL?
var friends: [User]?
var family: [String : User]?
init() {
}
static func map(inout object: User, json: Rosetta) {
object.ID <- json["uniqueID"] // Map required properties with <-
object.name <~ json["name"] // Map optional properties with <~
object.age <~ json["age"] § {$0 > 0} // Add validation closure after § operator (age > 0)
// Types not conforming to Bridgeable protocol (like NSURL here) need to have bridging code after ~ operator
object.website <~ json["website_url"] ~ BridgeString(
decoder: {NSURL(string: $0 as String)}, // convert NSString from json to NSURL
encoder: {$0.absoluteString} // convert NSURL from Person to NSString for JSON
)
object.friends <~ json["friends"] // Automaticaly mapped arrays
object.family <~ json["family"] // Automaticaly mapped dictionaries
}
}
然后您可以使用以下方式将 JSON
转换为 Person
let user = Rosetta().decode(jsonDataOrString) as User?
并将 Person
转换为 JSON
let jsonData = Rosetta().encode(user) as NSData?
let jsonString = Rosetta().encode(user) as String?
关于解码和编码如何工作的详细信息,请参阅 指南
如果要将某个字段定义为必填,请使用<-
运算符进行映射
object.name <- json["name"]
如果缺失此值或者不通过转换或验证,将会导致解码
/ 编码
失败。
若要将某字段视为可选,请使用<~
运算符进行映射
object.name <~ json["name"]
如果该字段缺失或不通过转换或验证,解码
/ 编码
不会完全失败,将跳过该字段并继续。
您可以使用~
运算符和bridge
将JSON
中的String
转换为NSURL
等。
object.url <~ json["URL"] ~ BridgeString(
decoder: {NSURL(string: $0 as String)},
encoder: {$0.absoluteString}
)
decoder
闭包从JSON中获取一个NSString
并转换为NSURL
。encoder
闭包则是相反的操作,返回NSURL
的字符串表示形式。
为了更加简洁,您可以将bridge
从函数中返回
func NSURLBridge() -> Bridge<NSURL, NSString> {
return BridgeString(
decoder: {NSURL(string: $0 as String)},
encoder: {$0.absoluteString}
)
}
然后进行映射
object.url <~ json["URL"] ~ NSURLBridge()
NSURLBridge()
实际上已经内置到Rosetta
中,但您可能会创建自己的其他桥接。
桥接是Rosetta
中非常重要且功能丰富的部分。它在内置指南中有详尽的解释。
您可以使用包含一系列的§
运算符(⌥6
)以及一个
(<SwiftPropertyType>)-> (BOOL)
闭包来进行验证。
object.age <~ json["age"] § {$0 > 0}
所以在示例中,age
(在验证闭包下用$0
传递的)必须大于0
。
有关验证的更多信息请参见指南
Rosetta
可以打印调试日志
Rosetta
ViewController.swift:904 handleResult()
JSON String: {"age":0,"website":"ftp://nonono.bad"}
Error: Value Missing for key-path: name
Error: Validation Failed for key-path: age
Warning: Validation Failed for key-path: website
日志默认是禁用的。您可以设置.logLevel
属性来启用它们
let rosetta = Rosetta()
rosetta.logLevel = .Errors
或者
rosetta.logLevel = .Verbose
您还可以更改日志输出(如果打印不合适)和自定义日志格式。所有这些都在指南中详细说明
struct CustomConvertibleType: JSONConvertible {
var someValue: Double?
init() {
}
static func map(inout object: CustomConvertibleType, json: Rosetta) {
object.someValue <- json["value"]
}
}
enum CustomBridgeableType: Int, Bridgeable {
case One = 1, Two, Three, Four
static func bridge() -> Bridge<CustomBridgeableType, NSNumber> {
return BridgeNumber(
decoder: {CustomBridgeableType(rawValue: $0.integerValue)},
encoder: {$0.rawValue}
)
}
}
struct YourCustomType: JSONConvertible {
var value1: Int?
var value2: CustomBridgeableType?
var value3: CustomConvertibleType?
var value4: NSURL?
var requiredValue1: String = ""
var requiredValue2: String!
var requiredValue3: String?
var validatedValue1: String?
var validatedValue2: CustomBridgeableType?
var validatedValue3: CustomConvertibleType?
var validatedValue4: NSURL?
var array1: [Int]?
var array2: [CustomBridgeableType]?
var array3: [CustomConvertibleType]?
var array4: [NSURL]?
var dictionary1: [String : Int]?
var dictionary2: [String : CustomBridgeableType]?
var dictionary3: [String : CustomConvertibleType]?
var dictionary4: [String : NSURL]?
init() {
}
static func map(inout object: YourCustomType, json: Rosetta) {
object.value1 <~ json["value1"]
object.value2 <~ json["value2"]
object.value2 <~ json["value3"]
object.value4 <~ json["value4"] ~ BridgeString(
decoder: {NSURL(string: $0 as String)},
encoder: {$0.absoluteString}
)
// Bridging placed in a constant just to reuse
let urlBridge = BridgeString(
decoder: {NSURL(string: $0 as String)},
encoder: {$0.absoluteString}
)
object.requiredValue1 <- json["required1"]
object.requiredValue2 <- json["required2"]
object.requiredValue3 <- json["required3"]
object.validatedValue1 <~ json["validated1"] § {$0.hasPrefix("requiredPrefix")}
object.validatedValue2 <~ json["validated2"] § {$0 == .One || $0 == .Three}
object.validatedValue3 <~ json["validated3"] § {$0.someValue > 10.0}
object.validatedValue4 <~ json["validated4"] ~ urlBridge § {$0.scheme == "https"}
object.array1 <~ json["array1"]
object.array2 <~ json["array2"]
object.array3 <~ json["array3"]
object.array4 <~ json["array4"] ~ BridgeArray(urlBridge)
object.dictionary1 <~ json["dictionary1"]
object.dictionary2 <~ json["dictionary2"]
object.dictionary3 <~ json["dictionary3"]
object.dictionary4 <~ json["dictionary4"] ~ BridgeObject(urlBridge)
}
}
Rosetta遵循MIT许可协议。更多信息请参阅LICENSE文件。