Skip to content

Instantly share code, notes, and snippets.

@colourful987
Last active August 29, 2016 15:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save colourful987/f9239a73044f10d090ab9865fcf29c6e to your computer and use it in GitHub Desktop.
Save colourful987/f9239a73044f10d090ab9865fcf29c6e to your computer and use it in GitHub Desktop.
Decoding JSON In Swift (一)
// From Soroush Khanlou ,URL: [Decoding JSON in Swift](http://khanlou.com/2016/04/decoding-json/)
import Foundation
struct ParserError:Error{
let message:String
}
struct Parser {
let dictionary : [String:AnyObject]?
init(dictionary:[String:AnyObject]?) {
self.dictionary = dictionary
}
func fetch<T>(key:String) throws -> T{
let fetchOptional = dictionary?[key] // 这里存在nil的情况
guard let fetched = fetchOptional else {
throw ParserError(message:"The key \(key) wa not found.")
}
// 由于开始是AnyObject 所以还要类型cast
guard let typed = fetched as? T else {
throw ParserError(message: "The key \"\(key)\" was not the correct type. It had value \"\(fetched).\"")
}
return typed
}
func fetch<T,U>(key:String,transformation:((T)->U?))throws -> U {
let fetched:T = try fetch(key: key)
guard let transformed = transformation(fetched) else {
throw ParserError(message: "The value \"\(fetched)\" at key \"\(key)\" could not be transformed.")
}
return transformed
}
// 有些情况是后台配置不同 可选的 即有时候有 有时候没有
func fetchOptional<T>(key: String) throws -> T? {
let fetchedOptional = dictionary?[key]
guard let fetched = fetchedOptional else {
return nil
}
guard let typed = fetched as? T else {
throw ParserError(message: "The key \"\(key)\" was not the right type. It had value \"\(fetched).\"")
}
return typed
}
func fetchOptional<T, U>(key: String, transformation: (T) -> U?) -> U? {
return (dictionary?[key] as? T).flatMap(transformation)
}
func fetchArray<T, U>(key: String, transformation: (T) -> U?) throws -> [U] {
let fetched: [T] = try fetch(key:key)
return fetched.flatMap(transformation)
}
}
enum SomeEnum: String {
case FirstCase = "first_case"
case SecondCase = "second_case"
}
struct InnerType {
let aString: String
let anInt: Int
let stringArray: [String]
let anOptionalValue: String?
init?(dictionary: [String: AnyObject]?) {
let parser = Parser(dictionary: dictionary)
do {
self.aString = try parser.fetch(key: "a_string")
self.anInt = try parser.fetch(key: "an_int")
self.stringArray = try parser.fetch(key: "string_array")
self.anOptionalValue = try parser.fetchOptional(key: "bingo")
} catch let error {
print(error)
return nil
}
}
}
class OuterType {
let inner: InnerType
let enums: [SomeEnum]
init?(dictionary: [String: AnyObject]?) {
let parser = Parser(dictionary: dictionary)
do {
// $0 其实inner 数据啦 当前是AnyObject
self.inner = try parser.fetch(key: "inner") { InnerType(dictionary: $0) }
self.enums = try parser.fetchArray(key: "enums") { SomeEnum(rawValue: $0) }
} catch let error {
print(error)
return nil
}
}
}
// 这里构造一个解析好的字典
var innerDictionary = [String: AnyObject]()
innerDictionary["a_string"] = "some_string" as? AnyObject
innerDictionary["an_int"] = 3 as? AnyObject
innerDictionary["string_array"] = ["a", "bunch", "of", "strings"] as? AnyObject
// 注意这里没有anOptionalValue 假定这里为nil 所以没有赋值
InnerType(dictionary: innerDictionary)
var outerDictionary = [String: AnyObject]()
outerDictionary["inner"] = innerDictionary as? AnyObject
outerDictionary["enums"] = ["first_case", "second_case"] as? AnyObject
let outer = OuterType(dictionary: outerDictionary)
print(outer?.inner.stringArray)
print(outer?.enums)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment