在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
开源软件名称:tristanhimmelman/ObjectMapper开源软件地址:https://github.com/tristanhimmelman/ObjectMapper开源编程语言:Swift 99.3%开源软件介绍:ObjectMapperObjectMapper is a framework written in Swift that makes it easy for you to convert your model objects (classes and structs) to and from JSON.
Features:
The BasicsTo support mapping, a class or struct just needs to implement the init?(map: Map)
mutating func mapping(map: Map) ObjectMapper uses the class User: Mappable {
var username: String?
var age: Int?
var weight: Double!
var array: [Any]?
var dictionary: [String : Any] = [:]
var bestFriend: User? // Nested User object
var friends: [User]? // Array of Users
var birthday: Date?
required init?(map: Map) {
}
// Mappable
func mapping(map: Map) {
username <- map["username"]
age <- map["age"]
weight <- map["weight"]
array <- map["arr"]
dictionary <- map["dict"]
bestFriend <- map["best_friend"]
friends <- map["friends"]
birthday <- (map["birthday"], DateTransform())
}
}
struct Temperature: Mappable {
var celsius: Double?
var fahrenheit: Double?
init?(map: Map) {
}
mutating func mapping(map: Map) {
celsius <- map["celsius"]
fahrenheit <- map["fahrenheit"]
}
} Once your class implements Convert a JSON string to a model object: let user = User(JSONString: JSONString) Convert a model object to a JSON string: let JSONString = user.toJSONString(prettyPrint: true) Alternatively, the // Convert JSON String to Model
let user = Mapper<User>().map(JSONString: JSONString)
// Create JSON String from Model
let JSONString = Mapper().toJSONString(user, prettyPrint: true) ObjectMapper can map classes composed of the following types:
|
ImmutableMappable | Mappable |
---|---|
Properties | |
let id: Int let name: String? |
var id: Int! var name: String? |
JSON -> Model | |
init(map: Map) throws { id = try map.value("id") name = try? map.value("name") } |
mutating func mapping(map: Map) { id <- map["id"] name <- map["name"] } |
Model -> JSON | |
func mapping(map: Map) { id >>> map["id"] name >>> map["name"] } |
mutating func mapping(map: Map) { id <- map["id"] name <- map["name"] } |
Initializing | |
try User(JSONString: JSONString) |
User(JSONString: JSONString) |
init(map: Map) throws
This throwable initializer is used to map immutable properties from the given Map
. Every immutable property should be initialized in this initializer.
This initializer throws an error when:
Map
fails to get a value for the given keyMap
fails to transform a value using Transform
ImmutableMappable
uses Map.value(_:using:)
method to get values from the Map
. This method should be used with the try
keyword as it is throwable. Optional
properties can easily be handled using try?
.
init(map: Map) throws {
name = try map.value("name") // throws an error when it fails
createdAt = try map.value("createdAt", using: DateTransform()) // throws an error when it fails
updatedAt = try? map.value("updatedAt", using: DateTransform()) // optional
posts = (try? map.value("posts")) ?? [] // optional + default value
surname = try? map.value("surname", default: "DefaultSurname") // optional + default value as an argument
}
mutating func mapping(map: Map)
This method is where the reverse transform is performed (model to JSON). Since immutable properties cannot be mapped with the <-
operator, developers have to define the reverse transform using the >>>
operator.
mutating func mapping(map: Map) {
name >>> map["name"]
createdAt >>> (map["createdAt"], DateTransform())
updatedAt >>> (map["updatedAt"], DateTransform())
posts >>> map["posts"]
}
ObjectMapper supports dot notation within keys for easy mapping of nested objects. Given the following JSON String:
"distance" : {
"text" : "102 ft",
"value" : 31
}
You can access the nested objects as follows:
func mapping(map: Map) {
distance <- map["distance.value"]
}
Nested keys also support accessing values from an array. Given a JSON response with an array of distances, the value could be accessed as follows:
distance <- map["distances.0.value"]
If you have a key that contains .
, you can individually disable the above feature as follows:
func mapping(map: Map) {
identifier <- map["app.identifier", nested: false]
}
When you have nested keys which contain .
, you can pass the custom nested key delimiter as follows (#629):
func mapping(map: Map) {
appName <- map["com.myapp.info->com.myapp.name", delimiter: "->"]
}
ObjectMapper also supports custom transforms that convert values during the mapping process. To use a transform, simply create a tuple with map["field_name"]
and the transform of your choice on the right side of the <-
operator:
birthday <- (map["birthday"], DateTransform())
The above transform will convert the JSON Int value to an Date when reading JSON and will convert the Date to an Int when converting objects to JSON.
You can easily create your own custom transforms by adopting and implementing the methods in the TransformType
protocol:
public protocol TransformType {
associatedtype Object
associatedtype JSON
func transformFromJSON(_ value: Any?) -> Object?
func transformToJSON(_ value: Object?) -> JSON?
}
In a lot of situations you can use the built-in transform class TransformOf
to quickly perform a desired transformation. TransformOf
is initialized with two types and two closures. The types define what the transform is converting to and from and the closures perform the actual transformation.
For example, if you want to transform a JSON String
value to an Int
you could use TransformOf
as follows:
let transform = TransformOf<Int, String>(fromJSON: { (value: String?) -> Int? in
// transform value from String? to Int?
return Int(value!)
}, toJSON: { (value: Int?) -> String? in
// transform value from Int? to String?
if let value = value {
return String(value)
}
return nil
})
id <- (map["id"], transform)
Here is a more condensed version of the above:
id <- (map["id"], TransformOf<Int, String>(fromJSON: { Int($0!) }, toJSON: { $0.map { String($0) } }))
Classes that implement the Mappable
protocol can easily be subclassed. When subclassing mappable classes, follow the structure below:
class Base: Mappable {
var base: String?
required init?(map: Map) {
}
func mapping(map: Map) {
base <- map["base"]
}
}
class Subclass: Base {
var sub: String?
required init?(map: Map) {
super.init(map)
}
override func mapping(map: Map) {
super.mapping(map)
sub <- map["sub"]
}
}
Make sure your subclass implementation calls the right initializers and mapping functions to also apply the mappings from your superclass.
ObjectMapper can handle classes with generic types as long as the generic type also conforms to Mappable
. See the following example:
class Result<T: Mappable>: Mappable {
var result: T?
required init?(map: Map){
}
func mapping(map: Map) {
result <- map["result"]
}
}
let result = Mapper<Result<User>>().map(JSON)
The Map
object which is passed around during mapping, has an optional MapContext
object that is available for developers to use if they need to pass information around during mapping.
To take advantage of this feature, simply create an object that implements MapContext
(which is an empty protocol) and pass it into Mapper
during initialization.
struct Context: MapContext {
var importantMappingInfo = "Info that I need during mapping"
}
class User: Mappable {
var name: String?
required init?(map: Map){
}
func mapping(map: Map){
if let context = map.context as? Context {
// use context to make decisions about mapping
}
}
}
let context = Context()
let user = Mapper<User>(context: context).map(JSONString)
If you are using Alamofire for networking and you want to convert your responses to Swift objects, you can use AlamofireObjectMapper. It is a simple Alamofire extension that uses ObjectMapper to automatically map JSON response data to Swift objects.
ObjectMapper and Realm can be used together. Simply follow the class structure below and you will be able to use ObjectMapper to generate your Realm models:
class Model: Object, Mappable {
dynamic var name = ""
required convenience init?(map: Map) {
self.init()
}
func mapping(map: Map) {
name <- map["name"]
}
}
If you want to serialize associated RealmObjects, you can use ObjectMapper+Realm. It is a simple Realm extension that serializes arbitrary JSON into Realm's List
class.
To serialize Swift String
, Int
, Double
and Bool
arrays you can use ObjectMapperAdditions/Realm. It'll wrap Swift types into RealmValues that can be stored in Realm's List
class.
Note: Generating a JSON string of a Realm Object using ObjectMappers' toJSON
function only works within a Realm write transaction. This is because ObjectMapper uses the inout
flag in its mapping functions (<-
) which are used both for serializing and deserializing. Realm detects the flag and forces the toJSON
function to be called within a write block even though the objects are not being modified.
Xcode Plugin for generating Mappable
and ImmutableMappable
code
Json4Swift - Supports generating ImmutableMappable
structs online (no plugins needed)
JSON to Model - Template based MacOS app which generates structs with customisation.
If you have a project that utilizes, extends or provides tooling for ObjectMapper, please submit a PR with a link to your project in this section of the README.
throws
Contributions are very welcome
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论