Rosetta 1.1.0

Rosetta 1.1.0

测试已测试
Lang语言 SwiftSwift
许可证 MIT
发布最新发布2016年11月
SwiftSwift 版本3.0
SPM支持 SPM

Bartek Chlebek 维护。



Rosetta 1.1.0

Rosetta

罗塞塔石碑是一块花岗闪长岩纪念碑,刻有公元前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 如何工作的简要概述,但应该可以给出您大致的概念。有关详尽的文档,请参阅 指南

JSON 解码/编码

使用 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"]

如果该字段缺失或不通过转换或验证,解码 / 编码不会完全失败,将跳过该字段并继续。

类型转换

您可以使用~运算符和bridgeJSON中的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文件。