I am using ObjectMapper
for a while and I find it cumbersome to write map function for classes with lots of property by using the way described in documents:
func mapping(map: Map) {
username <- map["username"]
age <- map["age"]
weight <- map["weight"]
array <- map["array"]
dictionary <- map["dictionary"]
bestFriend <- map["bestFriend"]
friends <- map["friends"]
}
I wonder if it is possible to use reflection to write map function like below assuming my JSON data and my class have axactly same property names:
func mapping(map: Map) {
let names = Mirror(reflecting: self).children.flatMap { $0.label }
for name in names {
self.value(forKey: name) <- map[name]
}
}
UPDATE:
Based on Sweeper's answer I have updated my code:
func mapping(map: Map) {
for child in Mirror(reflecting: self).children.compactMap({$0}) {
child <- map[child.label]
}
}
I guess this should work.
UPDATE 2:
Thanks to Sweeper, I have find out my initial guess was wrong and Child
is just a typealias for a touple:
public typealias Child = (label: String?, value: Any)
So my second attempt is also won't work.
The <-
operator is declared like this:
public func <- <T: RawRepresentable>(left: inout T, right: Map) {
left <- (right, EnumTransform())
}
As you can see, the left parameter is declared inout
. This means that you must use a mutable variable there, not the return value of some method.
So you do need to write all the properties.
I found this plugin that generates the mapping for you: https://github.com/liyanhuadev/ObjectMapper-Plugin
In Swift 4, Codable
is introduced and yet automatically works things out for you:
struct Foo: Codable {
var username: String
var age: Int
var weight: Double
// everything is done for you already! You don't need to write anything else
}