Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/ovenbits/ModelRocket
An iOS framework for creating JSON-based models. Written in Swift.
https://github.com/ovenbits/ModelRocket
Last synced: about 1 month ago
JSON representation
An iOS framework for creating JSON-based models. Written in Swift.
- Host: GitHub
- URL: https://github.com/ovenbits/ModelRocket
- Owner: ovenbits
- License: mit
- Created: 2015-08-24T20:12:29.000Z (over 9 years ago)
- Default Branch: master
- Last Pushed: 2016-09-01T02:04:46.000Z (over 8 years ago)
- Last Synced: 2024-04-25T00:32:17.237Z (8 months ago)
- Language: Swift
- Size: 91.8 KB
- Stars: 448
- Watchers: 14
- Forks: 19
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- awesome-swift-cn - ModelRocket - An iOS framework for creating JSON-based models. (Libs / Data Management)
README
![ModelRocket](https://s3.amazonaws.com/f.cl.ly/items/272x3d230n0Z3T300V1D/model-rocket.jpg)
[![Build Status](https://travis-ci.org/ovenbits/ModelRocket.svg?branch=master)](https://travis-ci.org/ovenbits/ModelRocket)
[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)
![CocoaPods Compatible](https://img.shields.io/cocoapods/v/ModelRocket.svg)
![License](https://img.shields.io/badge/license-MIT-000000.svg)
![Platform](https://img.shields.io/badge/platform-iOS-lightgrey.svg)An iOS framework for creating JSON-based models. Written in Swift (because [it totally rules!](https://youtu.be/Qq_NuyR8XPg?t=36s))
## Requirements
- iOS 8.0+
- Xcode 7.3
- Swift 2.2## Installation
> **Embedded frameworks require a minimum deployment target of iOS 8**
### Carthage
[Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager that automates the process of adding frameworks to your Cocoa application.
You can install Carthage with [Homebrew](http://brew.sh/) using the following commands:
```bash
$ brew update
$ brew install carthage
```To integrate ModelRocket into your Xcode project using Carthage, specify it in your [Cartfile](https://github.com/Carthage/Carthage/blob/master/Documentation/Artifacts.md#cartfile):
```ogdl
github "ovenbits/ModelRocket"
```Then, run `carthage update`.
Follow the current instructions in [Carthage's README](https://github.com/Carthage/Carthage#adding-frameworks-to-an-application) for up-to-date installation instructions.
### CocoaPods
[CocoaPods](http://cocoapods.org) is a dependency manager for Cocoa projects.
CocoaPods 0.36 adds supports for Swift and embedded frameworks. You can install it with the following command:
```bash
$ gem install cocoapods
```To integrate ModelRocket into your Xcode project using CocoaPods, specify it in your [Podfile](http://guides.cocoapods.org/using/the-podfile.html):
```ruby
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
use_frameworks!pod 'ModelRocket'
```Then, run `pod install`.
### Swift Package Manager
The [Swift Package Manager](https://swift.org/package-manager) is a dependency management tool provided by Apple, still in early design and development. For more infomation check out its [GitHub Page](https://github.com/apple/swift-package-manager).You can use the Swift Package Manager to install `ModelRocket` by adding it as a dependency in your `Package.swift` file:
```swift
import PackageDescriptionlet package = Package(
name: "PROJECT_NAME",
targets: [],
dependencies: [
.Package(url: "https://github.com/ovenbits/ModelRocket.git", versions: "1.2.3" ..< Version.max)
]
)
```## Usage
### Creating a custom object
```swift
class Vehicle: Model {
let make = Property(key: "make")
let model = Property(key: "model", required: true)
let year = Property(key: "year") { year in
if year < 2015 {
// offer discount
}
}
let color = Property(key: "color", defaultValue: UIColor.blackColor())
}
```
> NOTE: As with all Swift variables, `let` should always be used, unless `var` is absolutely needed. In the case of Model objects, `let` should be used for all `Property[Array|Dictionary]` properties, as it still allows the underlying `value` to be changed, unless you truly need to reassign the property#### Supported Types
- `String`
- `Bool`
- `Int`
- `UInt`
- `Double`
- `Float`In addition to the core types above, ModelRocket also supports serialization for several other
classes out of the box:- `NSDate` — ISO8601-formatted string (`2015-05-31T19:00:17.000+0000`)
- `UIColor` — hex-color string (`#f6c500`)
- `NSURL` — any url string (`http://ovenbits.com`)
- `NSNumber` — any number, can be used in place of `Double`, `Float`, `Int`, and `UInt`### Creating an object with a typed array
```swift
// `Model` subclasses get `fromJSON` and `toJSON` implementations on `JSONTransformable` for free,
// but explicit `JSONTransformable` conformance is still required
extension Vehicle: JSONTransformable {}class Vehicles: Model {
let vehicles = PropertyArray(key: "vehicles")
}
````PropertyArray` conforms to `CollectionType`, therefore, the `.values` syntax is not necessary when iterating through the values. For example:
```swift
let allVehicles = Vehicles(json: )// using `.values` syntax
for vehicle in allVehicles.vehicles.values {
}// using `CollectionType` conformance
for vehicle in allVehicles.vehicles {
}
```### Creating an object with a typed dictionary
```swift
class Car: Vehicle {
let purchasedTrims = PropertyDictionary(key: "purchased_trims")
}
````PropertyDictionary` conforms to `CollectionType`, therefore, the `.values` syntax is not necessary when iterating through the keys and values. For example:
```swift
let vehicle = Vehicle(json: )// using `.values` syntax
for (key, trim) in vehicle.purchasedTrims.values {
}// using `CollectionType` conformance
for (key, trim) in vehicle.purchasedTrims {
}
```> NOTE: All object in the dictionary must be of the same type. If they're not, the app won't crash, but values of different types will be discarded
### Initializing and using a custom object
```swift
// instantiate object
let vehicle = Vehicle(json: json)// get property type
println("Vehicle make property has type: \(vehicle.make.type)")// get property value
if let make = vehicle.make.value {
println("Vehicle make: \(make)")
}
```Model objects also contain a failable initializer, which will only return an initialized object if all properties marked as `required = true` are non-nil.
```swift
// instantiate object, only if `json` contains a value for the `make` property
if let vehicle = Vehicle(strictJSON: json) {
// it's best to avoid implicitly unwrapped optionals, however, since `vehicle` is initialized iff `make` is non-nil, if can be force-unwrapped safely here
println("Vehicle make: \(vehicle.make.value!)")
}
else {
pintln("Invalid JSON")
}
```### Subclassing a custom object
```swift
class Car: Vehicle {
let numberOfDoors = Property(key: "number_of_doors")
}
```### Adding a custom object as a property of another object
The custom object must conform to the JSONTransformable protocol by defining the following variables/functions
- class func fromJSON(json: JSON) -> T?
- func toJSON() -> AnyObject```swift
class Vehicle: Model {
let manufacturer = Property(key: "manufacturer")
}class Manufacturer: Model {
let companyName = Property(key: "company_name")
let headquarters = Property(key: "headquarters")
let founded = Property(key: "founded")
}extension Manufacturer: JSONTransformable {
class func fromJSON(json: JSON) -> Manufacturer? {
return Manufacturer(json: json)
}
func toJSON() -> AnyObject {
return self.json().dictionary
}
}
```### Using an enum as a property
ModelRocket supports enum types for `Property[Array|Dictionary]` properties, as long as the enum conforms to the `JSONTransformable` protocol.
As a simple example, the material type of a vehicle's interior could use an enum like this:
```swift
enum VehicleInterior: String {
case Fabric = "fabric"
case Leather = "leather"
}extension VehicleInterior: JSONTransformable {
static func fromJSON(json: JSON) -> VehicleInterior? {
return VehicleInterior(rawValue: json.stringValue)
}
func toJSON() -> AnyObject {
return rawValue
}
}class Vehicle: ModelRocket {
let interior = Property(key: "interior")
}```
### Property `postProcess` hook
The `Property` `postProcess` closure (also available on `PropertyArray` and `PropertyDictionary`) provides a mechanism for work to be done after all properties of a `Model` object have been initialized from JSON but before the `Model` object has finished initializing.
```swift
class Vehicles: Model {
let vehicles = PropertyArray(key: "vehicles") { (values) -> Void in
for vehicle in values {
println("postHook vehicle: \(vehicle.make.value!)")
}
}
}
```### `.value` accessor usage pattern
A ModelRocket property is of type `Property`. When accessing the property's value, you go through `Property.value`, e.g.:
```swift
let vehicleMake = make.value
```It is perfectly acceptable to to utilize `Property`s and access the property `value` directly. However, you may want a different public API for your model objects.
```swift
private let _make = Property(key: "make")
public var make: String {
get {
return make.value ?? "unknown make"
}
set {
make.value = newValue
}
}
```This usage pattern enables:
- A cleaner public API
- A public API that makes the type more proper: we expect "make" to be a string, not a `Property`
- `value` is optional because it must be for general applicability, but your API may be more correct to have non-optional. Of course, if your API wants an optional, that's fine too.
- The ability to process or convert the raw JSON value to other values more proper to your object's public API
- Whereas a `Property.value` could be set, you could omit the set accessor for a read-only property, again helping to expose exactly the API for your object that you desire.
- This usage of the bridge pattern enables ModelRocket to become an implementation detail and minimize dependencies and long-term maintenance.### Implementing a class cluster
Override the `modelForJSON(json: JSON) -> Model` function```swift
class Vehicle: Model {
let make = Property(key: "make")
let model = Property(key: "model")
let year = Property(key: "year")
let color = Property(key: "color")
let manufacturer = Property(key: "manufacturer")
override class func modelForJSON(json: JSON) -> Vehicle {
switch json["type"].stringValue {
case "car":
return Car(json: json)
case "plane":
return Plane(json: json)
case "bike":
return Bike(json: json)
default:
return Vehicle(json: json)
}
}
}
```Then to access subclass-specific properties, use a switch-case
```swift
let vehicle = Vehicle.modelForJSON(vehicleJSON)
switch vehicle {
case let car as Car:
// drive the car
case let plane as Plane:
// fly the plane
case let bike as Bike:
// ride the bike
default:
// do nothing
}
```### Obtaining the object's JSON representation
Calling the `json()` function on a Model subclass returns a tuple containing:
- `dictionary: [String : AnyObject]`
- `json: JSON`
- `data: NSData`### Obtaining a copy of a custom object
Call `copy()` on the object, and cast to the correct type. Example:
```swift
let vehicleCopy = vehicle.copy() as! Vehicle
```## License
ModelRocket is released under the MIT license. See LICENSE for details.