【问题标题】:Use dynamic CodingKeys to decode JSON in Swift在 Swift 中使用动态 CodingKeys 解码 JSON
【发布时间】:2019-11-14 23:37:06
【问题描述】:

我想不出使用 Swift 解码这个 JSON 的方法。 我尝试遵循一堆教程和指南,但没有什么对我有用。

我能够添加静态 CodingKeys 的唯一内容是:“especificaciones”、“id”、“titulo" "默认"

"especificaciones" : {
 "EXTERIOR" : {
  "sistema_automatico_de_ajuste_de_altura_para_faros" : {
    "id" : "865",
    "titulo" : "Sistema automatico de ajuste de altura para faros",
    "default" : ""
  },
  "antena_" : {
    "id" : "1366",
    "titulo" : "Antena ",
    "default" : ""
  },
  "luces_direccionales_en_espejos_laterales" : {
    "id" : "734",
    "titulo" : "Luces direccionales en espejos laterales",
    "default" : ""
  },
  "faros_traseros" : {
    "id" : "1430",
    "titulo" : "Faros traseros",
    "default" : ""
  },
},
 "DIMENSIONES INTERIORES" : {
  "espacio_para_las_piernas___delantera_trasera" : {
    "id" : "1417",
    "titulo" : "Espacio para las piernas - delantera/trasera",
    "default" : ""
  },
  "espacio_para_los_hombros____delantera_trasera" : {
    "id" : "1418",
    "titulo" : "Espacio para los hombros -  delantera/trasera",
    "default" : ""
  },
  "area_de_carga__l_" : {
    "id" : "1498",
    "titulo" : "Area de carga (L)",
    "default" : ""
  }
}

}

这不是整个 JSON,但可能通过它您可以了解我在寻找什么。

【问题讨论】:

  • 由于您不知道用户将创建什么类别,您需要使用动态编码键。您可以使用有效的 JSON 更新问题吗?以便我们获得更多信息。

标签: json swift codable


【解决方案1】:
{ "especificaciones": { "RINES Y LLANTAS": { "llantas_delanteras": { "id": "935", "titulo": "Llantas delanteras", "default": "" }


private struct CustomCodingKeys: CodingKey {
    var stringValue: String
    init?(stringValue: String) {
        self.stringValue = stringValue
    }
    var intValue: Int?
    init?(intValue: Int) {
        return nil
    }
}

struct RootOutput {
    var entities:Entities?
    var mainRoot:String?
    var subRoot:String?
}


struct Root: Decodable {

    var rootLevel: SubTopRoot?

    init(from decoder: Decoder)  {
        do{
            let container = try decoder.container(keyedBy: CustomCodingKeys.self)
            for key in container.allKeys{
               rootLevel = try container.decodeIfPresent(SubTopRoot.self, forKey: CustomCodingKeys.init(stringValue: key.stringValue)!)
            }
        }catch{
            print(error.localizedDescription)
        }
    }
}

struct SubTopRoot: Decodable {

    var subTopLevel:SubRoot?

    init(from decoder: Decoder)  {
        do{
            let container = try decoder.container(keyedBy: CustomCodingKeys.self)
            for key in container.allKeys{
                subTopLevel = try container.decodeIfPresent(SubRoot.self, forKey: CustomCodingKeys.init(stringValue: key.stringValue)!)
                for index in 0..<(subTopLevel?.SubRootLevel.count ?? 0){
                    subTopLevel?.SubRootLevel[index].mainRoot = key.stringValue
                }
           }
        }catch{
            print(error.localizedDescription)
        }
    }


}

struct SubRoot: Decodable {

    var SubRootLevel:[RootOutput] = [RootOutput]()

    init(from decoder: Decoder)  {
        do{
            let container = try decoder.container(keyedBy: CustomCodingKeys.self)
            for key in container.allKeys{
                let entities = try container.decodeIfPresent(Entities.self, forKey: CustomCodingKeys.init(stringValue: key.stringValue)!)
                SubRootLevel.append(RootOutput.init(entities: entities, mainRoot:"" , subRoot: key.stringValue))
            }

        }catch{
            print(error.localizedDescription)
        }
    }

}

struct Entities: Codable {
    var id: String?
    var titulo: String?
    var defaultItem: String?

    init(from decoder: Decoder)  {
        do{
            let container = try decoder.container(keyedBy: CodingKeys.self)
                self.id = try container.decodeIfPresent(String.self, forKey: .id)
                self.titulo = try container.decodeIfPresent(String.self, forKey: .titulo)
                self.defaultItem = try container.decodeIfPresent(String.self, forKey: .defaultItem)


        }catch{
            print(error.localizedDescription)
        }
    }

    enum CodingKeys: String, CodingKey {
        case id = "id"
        case titulo = "titulo"
        case defaultItem = "default"
    }
}

希望对你有帮助!

//Dummy Test
   do {

            let dataString = "{\r\n\t\"especificaciones\": {\r\n\t\t\"RINES Y LLANTAS\": {\r\n\t\t\t\"llantas_delanteras\": {\r\n\t\t\t\t\"id\": \"935\",\r\n\t\t\t\t\"titulo\": \"Llantas delanteras\",\r\n\t\t\t\t\"default\": \"\"\r\n\t\t\t},\r\n\t\t\t\"llantas_traseras\": {\r\n\t\t\t\t\"id\": \"936\",\r\n\t\t\t\t\"titulo\": \"Llantas traseras\",\r\n\t\t\t\t\"default\": \"\"\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}"
            let data = Data(dataString.utf8)
            //here dataResponse received from a network request
            let decoder = JSONDecoder()
            let model = try decoder.decode(Root.self, from:data) //Decode JSON Response Data
            print(model.rootLevel?.subTopLevel?.SubRootLevel)
        } catch let parsingError {
            print("Error", parsingError)
        }

    }

【讨论】:

  • 我试过了,它返回给我:无法读取数据,因为它的格式不正确。根(rootLevel: 可选(TodoEnSubastas.SubTopRoot(subTopLevel: 可选(TodoEnSubastas.SubRoot(SubRootLevel: []))))) 可选([])
  • 您发布的 json 无效...可能是它的抛出错误
  • { "especificaciones": { "RINES Y LLANTAS": { "llantas_delanteras": { "id": "935", "titulo": "Llantas delanteras", "default": "" } , "llantas_traseras": { "id": "936", "titulo": "Llantas traseras", "default": "" } } } } 这是您发布的上述 json 的正确格式
猜你喜欢
  • 2020-08-15
  • 1970-01-01
  • 1970-01-01
  • 2019-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-17
  • 1970-01-01
相关资源
最近更新 更多