Skip to content
PonyCui edited this page Jul 1, 2015 · 9 revisions

PPJSONSerialization

介绍

PPJSONSerialization 是使用Swift语言编写的JSON解析Helper类,它可以帮助你将JSON数据转换成Swift实体类。

感谢 SwiftyJSON (https://github.com/SwiftyJSON/SwiftyJSON) 为我们开源了一个相当易用的JSON库。

使用 SwiftyJSON 的方法就像下面这样。

let json = JSON(data: dataFromNetworking)
if let userName = json[0]["user"]["name"].string{
  //Now you got your value
}

我的个人看法是,既然苹果给予了我们一个强类型的语言,我们为什么不去好好利用呢?

所以,当你使用 PPJSONSerialization 的时候,代码会是这样子的。

// 定义一个类 ```SimpleStruct```;
// 所有的属性都必须给定一个默认值并且指明类型。
class SimpleStruct: PPJSONSerialization {
    var simpleStr = ""
    var simpleInt = 0
    var simpleBool = false
    var simpleDouble = 0.0
    var simpleArray = [0]
}

let simpleJSON = "{\"simpleStr\":\"String Value\", \"simpleInt\":1024, \"simpleBool\": true, \"simpleDouble\": 1024.00, \"simpleArray\": [1,0,2,4]}"
if let simpleObject = SimpleStruct(JSONString: simpleJSON) {
   print(simpleObject.simpleStr) // 使用JSON的值就像使用类的属性一样简单
}

不用担心类型问题,你为SimpleStruct当中的属性指定了类型,PPJSONSerialization会尽一切能力将值转换过来。

func testTypeTransfer() {
  let typeErrorJSON = "{\"simpleStr\": 1024, \"simpleInt\": \"1024\", \"simpleBool\": null, \"simpleDouble\": \"Bool Value\", \"simpleArray\": {}}"
  if let simpleObject = SimpleStruct(JSONString: typeErrorJSON) {
    XCTAssert(simpleObject.simpleStr == "1024", "Pass")
    XCTAssert(simpleObject.simpleInt == 1024, "Pass")
    XCTAssert(simpleObject.simpleBool == false, "Pass")
    XCTAssert(simpleObject.simpleDouble == 0.0, "Pass")
    XCTAssert(simpleObject.simpleArray.count <= 0, "Pass")
  }
}

你定义的结构类可能包含另一个结构类,又或者数组里面包含的是另一个结构类的集合,PPJSONSerialization可以轻松应对这种情况。

// 定义一个结构类,BuildingStruct
class BuildingStruct: PPJSONSerialization {
    var buildNumber = ""
    var managementRoom = RoomStruct()
    var buildRooms = [RoomStruct()]
}

// 定义另一个结构类,RoomStruct
class RoomStruct: PPJSONSerialization {
    var roomNumber = 0
    var roomSize: Double = 0.0
    
    // 如果这个结构会被数组包含,那么改写copyWithZone并返回自身的新实例是必要的。
    override func copyWithZone(zone: NSZone) -> AnyObject {
        return RoomStruct()
    }
}

func testDictionaryContainsJSON() {
  let dictionaryContainsJSON = "{\"buildNumber\": \"B\", \"managementRoom\":{\"roomNumber\":101, \"roomSize\":10.14}, \"buildRooms\":[{\"roomNumber\":632, \"roomSize\":6.6}, {\"roomNumber\":633, \"roomSize\":6.7}]}"
  if let buildingObject = BuildingStruct(JSONString: dictionaryContainsJSON) {
    XCTAssert(buildingObject.buildNumber == "B", "Pass")
    XCTAssert(buildingObject.managementRoom.roomNumber == 101, "Pass")
    XCTAssert(buildingObject.managementRoom.roomSize == 10.14, "Pass")
    XCTAssert(buildingObject.buildRooms.count == 2, "Pass")
    XCTAssert(buildingObject.buildRooms[0].roomNumber == 632, "Pass")
    XCTAssert(buildingObject.buildRooms[0].roomSize == 6.6, "Pass")
    XCTAssert(buildingObject.buildRooms[1].roomNumber == 633, "Pass")
    XCTAssert(buildingObject.buildRooms[1].roomSize == 6.7, "Pass")
  }
}

改写mapping()方法,返回自己的map数据,这样你就可以将JSON的字段映射到Class里面的自定义字段了。

// Define a Map Struct and override mapping() return, you can map the JSON key to Custom Property key
class MapStruct: PPJSONSerialization {
    override func mapping() -> [String : String] {
        return ["mapStr": "simpleStr"]
    }
    
    var simpleStr = ""
}
func testMapping() {
  let simpleJSON = "{\"mapStr\": \"String Value\"}"
  if let simpleObject = MapStruct(JSONString: simpleJSON) {
    XCTAssert(simpleObject.simpleStr == "String Value", "Pass")
  }
}

PPJSONSerialization 仍然在开发中,欢迎fork和pull request。

要求

  • iOS 7.0+ / Mac OS X 10.10+
  • Xcode 6.3
  • 暂时不支持 Xcode7.0 beta, Swift2.0仍然在改动中,在Swift2.0正式发布后,PPJSONSerialization再作兼容。

安装

PPJSONSerialization.swift 添加到你的工程里面

协议

MIT License 自由使用

感谢

感谢 @onevcat 喵大建议加入Failable init

Clone this wiki locally