【问题标题】:ObjectMapper - map JSON dictionary as nested objectObjectMapper - 将 JSON 字典映射为嵌套对象
【发布时间】:2019-08-03 07:52:23
【问题描述】:

我正在尝试使用 ObjectMapper 来使用 JSON 响应。到目前为止,我的回复是这样的:

{
  "paramsStructure": [
    {
      "tiles": {
        "0": {
          "layout": {
            "column": 0,
            "colSpan": "1",
            "rowSpan": "1",
            "row": 0
          },
          "type": "2"
        },
        "1": {
          "layout": {
            "column": 1,
            "colSpan": "1",
            "rowSpan": "1",
            "row": 0
          },
          "type": "2"
        }
      },
      "title": "...",
      "rowCount": "4",
      "colCount": "2",
      "key": "...",
      "icon": "..."
    }
  ]
}

到目前为止,我已经为整个 paramsStructure 和 Single Structure 对象的嵌套集合创建了 StructuresObject。现在我想将图块映射到嵌套在 Structure 对象中的 TileStructure 对象集合中,如下所示。

class SingleStructure : Mappable{

    var columns: Int = 0
    var title: String = ""
    var key: String = ""
    var icon: String = ""
    var tilesStructure : [Int: TileStructure]?

    required init?(map: Map) {

    }

    func mapping(map: Map) {
        title <- map["title"]
        key <- map["key"]
        icon <- map["icon"]
        columns <- (map["colCount"], TransformOf<Int, String>(
            fromJSON: {item in return Int(item!)},
            toJSON: {_ in return "$0"}))


        //need here parsing of tilesStructure
     }
}

我主要需要将此 JSON 切片字典映射到 [Int: TileStructure] 中,其中键是字典键,TileStructure 是包含“布局”和“类型”属性的可映射对象。

提前感谢您的帮助:)

编辑!!!

我尝试了 denis_lor 方法,但是当我从 RxAlamofire 运行解析数据时,出现以下异常:

keyNotFound(CodingKeys(stringValue: "tiles", intValue: nil), Swift.DecodingError.Context(codingPath: [], debugDescription: "No value associated with key CodingKeys(stringValue: \"tiles\", intValue: nil) (\"tiles\").", underlyingError: nil))

这就是我调用请求的方式

 return RxAlamofire.requestData(.get, GlobalSettings.GET_DEVICE_MAIN_STRUCTURE, parameters: parameters, headers: headers)
        .debug()

        .mapObject(type: ParamsStructure.self)

这就是我的对象映射器:

extension ObservableType {

public func mapObject<T: Codable>(type: T.Type) -> Observable<T> {
    return flatMap { data -> Observable<T> in
        let responseTuple = data as? (HTTPURLResponse, Data)

        guard let jsonData = responseTuple?.1 else {
            throw NSError(
                domain: "",
                code: -1,
                userInfo: [NSLocalizedDescriptionKey: "Could not decode object"]
            )
        }

        let decoder = JSONDecoder()

        let object = try decoder.decode(T.self, from: jsonData)

        return Observable.just(object)
    }
}

}

我认为问题可能出在编码上,这就是造成那些转义“\”的原因,而这些转义符属于键不匹配。

【问题讨论】:

    标签: swift objectmapper rxalamofire


    【解决方案1】:

    这里使用具有动态键的 json 结构的关键是使用 Dictionary,就像我对 [String:Tile] 所做的那样。

    你可以试试新的Swift4's Codable

    import Foundation
    
    public struct ResultParamsStructure: Codable {
        public var paramsStructure: [ParamsStructure] = []
    
        enum CodingKeys: String, CodingKey {
            case paramsStructure = "paramsStructure"
        }
    }
    
    public struct ParamsStructure: Codable {
        public var tiles: [String:Tile] = [:]
        public var title: String = ""
        public var rowCount: String = ""
        public var colCount: String = ""
        public var key: String = ""
        public var icon: String = ""
    
        enum CodingKeys: String, CodingKey {
            case tiles = "tiles"
            case title = "title"
            case rowCount = "rowCount"
            case colCount = "colCount"
            case key = "key"
            case icon = "icon"
        }
    }
    
    public struct Tile: Codable {
        public var layout: Layout?
        public var type: String = ""
    
        enum CodingKeys: String, CodingKey {
            case layout = "layout"
            case type = "type"
        }
    }
    
    public struct Layout: Codable {
        public var column: Int = 0
        public var colSpan: String = ""
        public var rowSpan: String = ""
        public var row: Int = 0
    
        enum CodingKeys: String, CodingKey {
            case column = "column"
            case colSpan = "colSpan"
            case rowSpan = "rowSpan"
            case row = "row"
        }
    }
    
    let jsonString = """
    {
      "paramsStructure": [
        {
          "tiles": {
            "0": {
              "layout": {
                "column": 0,
                "colSpan": "1",
                "rowSpan": "1",
                "row": 0
              },
              "type": "2"
            },
            "1": {
              "layout": {
                "column": 1,
                "colSpan": "1",
                "rowSpan": "1",
                "row": 0
              },
              "type": "2"
            }
          },
          "title": "...",
          "rowCount": "4",
          "colCount": "2",
          "key": "...",
          "icon": "..."
        }
      ]
    }
    """
    
    let json = jsonString.data(using: .utf8)!
    
    let resultParamsStructure = try? JSONDecoder().decode(ResultParamsStructure.self, from: json)
    
    print(resultParamsStructure?.paramsStructure[0].tiles.keys)
    print(resultParamsStructure?.paramsStructure[0].tiles["1"]?.layout?.colSpan)
    //# Optional(Dictionary.Keys(["0", "1"]))
    //# Optional("1")
    

    你可以在这里试试上面的代码:http://online.swiftplayground.run/

    【讨论】:

    • 检查您的方法后,我遇到了另一个问题。我在问题更新中描述了它。你有什么想法我该如何解决这个问题?
    • 那是正确的 JSON 吗?还是要再买一个?
    • 我传递给你的是那个 json 的一部分,我只是剪切了一些我没有解析的数据,放在与“paramsStructure”相同的 lvl 上。我传递的 json 是 Postman 获取的。
    • 好的,它说缺少 CodingKeys,我添加了它们,你可以重试吗? @MaciejGrodzki
    • 可悲的是,它仍然是同样的例外。它搜索“tiles”而不是“tiles”。您是否在 RxAlamofire 中使用了这种编码方法。也许使用 ObjectMapper 也可以实现相同的目标,因为他使用 RxAlamofire.requestJSON 结果,并且到目前为止效果很好。
    猜你喜欢
    • 2018-04-29
    • 1970-01-01
    • 1970-01-01
    • 2021-07-06
    • 2016-11-15
    • 1970-01-01
    • 2020-09-27
    • 2013-08-01
    • 1970-01-01
    相关资源
    最近更新 更多