FunctionalJSON 0.1.0

FunctionalJSON 0.1.0

测试已测试
语言语言 SwiftSwift
许可证 MIT
发布上次发布2015年11月
SPM支持SPM

Antoine Palazzolo维护。



FunctionalJSON

FunctionalJSON是Swift的一个快速、函数式JSON库。
灵感来源于play/scala JSON库。

特性

  • 简单的读取求组合以构建复杂结构
  • 完整的JSON验证和易于调试
  • 轻松导航到JSON树
  • 简单语法
  • 快!

使用方法

json

{
    "customers" : [
        {
            "name" : "alice",
            "age" : 20,
            "transactions" : [{"id" : 21312},{"id" : 32414},{"id" : 23443}]
        },
        {
            "name" : "bob",
            "transactions" : []
        },
        {
            "name" : "chris",
            "age" : 34,
            "transactions" : [{"id" : 23455},{"id" : 23452}]
        }
    ] 
}

swift

import FunctionalJSON
import FunctionalBuilder

struct Person : JSONReadable {
    let name : String
    let age : Int?
    let transactions : [Transaction]

    static let jsonRead = JSONRead(
        JSONPath("name").read(String) <&>
        JSONPath("age").read(Int?) <&>
        JSONPath("transactions").read([Transaction])
    ).map(Person.init)
}
struct Transaction : JSONReadable {
    let identifier : Int64
    static let jsonRead = JSONPath("id").read(Int64).map(Transaction.init)
}

let jsonData : NSData = ... 
let json = try JSONValue(data : jsonData)

let persons : [Person] = try json["customers"].validate([Person])  

JSONValue

结构体JSONValue包含解析的JSON数据。

let jsonData : NSData = ... 
let json = try JSONValue(data : jsonData)

输入数据使用Foundation NSJSONSerialization进行解析。
可以将解析选项作为初始化参数传递

let json = try JSONValue(data: jsonData, options : [.AllowFragments])

导航到JSON树

使用中括号和JSONPath进行导航

let jsonElement : JSONValue = json[JSONPath("customers",0)]


let jsonElement : JSONValue = json["customers"][0] <br />


let jsonElement : JSONValue = json["customers",0]

JSONPathJSONPathComponent数组的外包装器

public enum JSONPathComponent {
    case Key(String)
    case Index(Int)
}

一个Key值代表JSON对象的键,一个Index代表JSON数组中的索引。

此方法始终返回一个JSONValue,即使JSON树中没有相应的值。

isNull属性将在没有值时返回true

let isNull : Bool = json["customers",1992002].isNull



isEmpty属性将在没有底层值或是一个空对象或数组时返回true

let isEmpty : Bool = json["customers"].isEmpty

JSONRead

结构体JSONRead<T>定义了从JSON中读取值的方式。它包含元素路径和将元素验证和转换为类型T的的目标值的函数。
所有基本JSON类型都已实现并映射到Swift类型。(Int..DoubleFloatStringArray

JSONRead可以用以下方式进行转换:

map<U>(t : T throws -> U) -> JSONRead<U>

示例

  • 在路径“customers”/0/“age”处读取一个Int
let read : JSONRead<Int> = JSONPath(["customers",0,"age"]).read(Int)
  • 转换为日期时间读取
let readDate : JSONRead<NSDate> = read.map {
    guard let date = NSCalendar.currentCalendar().dateByAddingUnit(.Year,
        value: -$0,
            toDate: NSDate(),
               options: []) else {
               throw Error.DateError
           }
           return date
       }
  • 如果失败,进行可选读取
let optionalRead : JSONRead<NSDate?> = readDate.optional
  • 如果读取失败,返回默认值
let defaultDateRead : JSONRead<NSDate> = readDate.withDefault(NSDate())

使用方法

let jsonValue : JSONValue = ...
do {
    let date : NSDate = try jsonValue.validate(defaultDateRead)
} catch {
    ...
}

JSONReadable

public protocol JSONReadable {
    static var jsonRead : JSONRead<Self> {get}
}

JSONReadable 协议用于获取类型的默认读取操作。它不能应用于非最终 class,因为子类无法重新声明其类型的 jsonRead 静态变量。
此协议使得在 JSONValue 验证和 JSONPath 读取方法中启用“类型”语法。

JSONPath("name").read(String)

而不是

JSONPath("name").read(String.jsonRead)

组合

组合和 <& 操作符来自 FunctionalBuilder 模块。该模块用于组合泛型抛出函数并累积错误。您可以组合多达 10 次读取。

let read : JSONRead<(String,Int?,[Transaction])> = JSONRead(
    JSONPath("name").read(String) <&>
    JSONPath("age").read(Int?) <&>
    JSONPath("transactions").read([Transaction])
)

验证

与其他 json 库不同,验证不会在第一个错误处停止。相反,所有错误都会累积并最终以错误列表的形式报告出来。

使用前几次读取验证此 JSON

{
    "name" : 31232,
    "age" : 30,
    "transactions" : [{"identifier" : 23455},{"id" : 23455}]
}


let json = try JSONValue(data : jsonData)
do {
    try json.validate(Person)
} catch {
    print(error)
}

这将抛出一个包含 2 个错误的 JSONValidationError 异常。

JSON Errors :
    JSON Bad value type -> "name"
    JSON Value not found -> "transactions/0/id"