如何使用ObjectMapper将自定义Enum / RawRepresentable映射到字典?

时间:2016-07-13 08:32:22

标签: ios swift enums nsdictionary objectmapper

使用以下简化结构:

class Property: Mappable {
    var path: String?

    override func mapping(map: Map) {
        path <- map["path"]
    }
}

class Specification {
    enum Name: String {
        case Small = "SMALL"
        case Medium = "MEDIUM"
    }
}

class ItemWithImages: Mappable {
    var properties: [Specification.Name : Property]?

    override func mapping(map: Map) {
        properties <- (map["properties"], EnumTransform<Specification.Name>())
    }
}

......用那个JSON:

[{"properties: ["SMALL": {"path": "http://..."}, "MEDIUM": {"path": "http://..."}]}]

...使用EnumTransform()生成以下(合理的)编译错误:

Binary operator '<-' cannot be applied to operands of type '[Specification.Name : Property]?' and '(Map, EnumTransform<Specification.Name>)'

那么自定义TransformType必须如何,以正确的方式映射该字典?

您可以在此处找到EnumTransform的来源:https://github.com/Hearst-DD/ObjectMapper/blob/master/ObjectMapper/Transforms/EnumTransform.swift

谢谢!

2 个答案:

答案 0 :(得分:1)

TransformTypes是IMHO的主要设计用于转换值而不是键。你的例子有点复杂,因为即使价值不仅仅是基本类型。

你怎么看待这个小黑客?

struct ItemWithImages: Mappable {
    var properties: [Specification.Name : Property]?

    init?(_ map: Map) {
    }

    mutating func mapping(map: Map) {
        let stringProperties: [String: Property]?
        // map local variable
        stringProperties <- map["properties"]

        // post process local variable
        if let stringProperties = stringProperties {
            properties = [:]
            for (key, value) in stringProperties {
                if let name = Specification.Name(rawValue: key) {
                    properties?[name] = value
                }
            }
        }
    }
}

答案 1 :(得分:0)

我们应该使用DictionaryTransform而不是EnumTransform。我们正在将Dictionary [String:Any]的类型转换为[Key:Value]。在我们的案例中,类型是[Specification.Name:Property]。

符合Hashable,RawRepresentable和Key.RawValue等协议的关键需要是String。

值应该符合可映射协议。

    class Property: Mappable {
        var path: String?

        override func mapping(map: Map) {
            path <- map["path"]
        }
    }

    class Specification {
        enum Name: String {
            case Small = "SMALL"
            case Medium = "MEDIUM"
        }
    }

    class ItemWithImages: Mappable {
        var properties: [Specification.Name : Property]?

        override func mapping(map: Map) {
            properties <- (map["properties"], DictionaryTransform<Specification.Name,Property>())
        }
    }