JSONCodable 3.0.1

JSONCodable 3.0.1

测试测试通过
语言编程语言 SwiftSwift
许可证 MIT
发布最新发布2016年11月
SwiftSwift 版本3.0
SPM支持 SPM

Matthew CheokNadohs维护。



  • Matthew Cheok

Logo

JSONCodable

Swift 中轻松进行 JSON 编码和解码

安装

  • 只需将以下内容添加到 Cartfile 并运行 carthage update
github "matthewcheok/JSONCodable" ~> 3.0
  • 或将其添加到您的 Podfile 并运行 pod install
pod 'JSONCodable', '~> 3.0'
  • 或将其作为 Git 子模块克隆,

  • 或只需将 JSONCodable 文件夹中的文件复制到您的项目中。

TLDR

  • 使用协议扩展
  • 错误处理
  • 支持 let 属性
  • 支持由兼容值支持的 enum 属性

变更日志

  • 将编码和解码方法移动到辅助类中


JSONCodable 由两个独立的协议 JSONEncodableJSONDecodable 组成。

  • JSONEncodable 允许您的结构和类生成 NSDictionary[String: AnyObject] 等价物,用于与 NSJSONSerialization 一起使用。

  • JSONDecodable 允许您从包含网络请求等内容的 NSDictionary 生成结构。

解码 JSON

以这些两个类型为例

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

编码 JSON

只需添加符合性到 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;
    }
)]

处理JSON字符串

JSONDecodable上提供了便利的初始化器init?(JSONString: String)。您还可以使用func toJSONString() throws -> String来获取您类型的字符串等效形式。

值转换

要转换值,创建一个JSONTransformer实例

let JSONTransformerStringToNSURL = JSONTransformer<String, NSURL>(
        decoding: {NSURL(string: $0)},
        encoding: {$0.absoluteString})

JSONTransformer在两种类型之间转换,在这种情况下是StringNSURL。它需要一个用于解码的闭包和一个用于编码的闭包,在每种情况下,给定输入类型,您都返回相应类型的可选值(如果转换不可行,您可以返回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格式

随时提出建议!

扩展JSONCodable(感谢@raylillywhite)

这允许对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许可。