You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift自定义解码:合并属性构建Dog与Cat结构体

Swift中MyPets结构体JSON解码问题的解决方案

问题背景

需要将给定的JSON数据解码到MyPets结构体中,核心需求是将顶层的catName/dogName字段,与嵌套在cat/dog对象中的属性合并,分别构建完整的Cat和Dog实例。原尝试因未正确实现解码逻辑,且未处理JSON中weight字段的字符串转Int问题,导致解码失败。

原结构体代码:

struct MyPets: Decodable {
  let dog: Dog
  let cat: Cat

  // enum CodingKeys: String, CodingKey {
  //   case dog 
  //   case cat
  //   case catName
  //   case dogName
  // }

   public init(from decoder: Decoder) throws {
    let values = try decoder.container(keyedBy: CodingKeys.self)
    // values only has dog and cat
   }
}

struct Dog {
  let name: String
  let weight: Int
  let food: String
}

struct Cat {
  let name: String
  let weight: Int
  let food: String
}

对应JSON数据:

{
   "catName": "fluffy", 
   "dogName": "softy", 
   "cat": {
       "food": "fancyFeast", 
       "weight": "8"
   }, 
   "dog": {
       "food": "kibble", 
       "weight": "9"
   }
}

解决方案

通过完善CodingKeys定义、自定义解码逻辑,并处理字符串转Int的类型转换,实现属性合并解码:

struct MyPets: Decodable {
    let dog: Dog
    let cat: Cat

    // 定义包含所有需要字段的CodingKeys
    enum CodingKeys: String, CodingKey {
        case dog, cat, catName, dogName
    }

    public init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        
        // 解码顶层的宠物名称
        let catName = try container.decode(String.self, forKey: .catName)
        let dogName = try container.decode(String.self, forKey: .dogName)
        
        // 临时结构体用于解码嵌套对象中的字符串类型weight
        struct TempPet: Decodable {
            let food: String
            let weight: String
        }
        
        // 解码嵌套的cat和dog临时对象
        let tempCat = try container.decode(TempPet.self, forKey: .cat)
        let tempDog = try container.decode(TempPet.self, forKey: .dog)
        
        // 将字符串weight转换为Int,转换失败则抛出解码错误
        guard let catWeight = Int(tempCat.weight),
              let dogWeight = Int(tempDog.weight) else {
            throw DecodingError.dataCorruptedError(
                forKey: .cat, 
                in: container, 
                debugDescription: "weight字段无法转换为整数类型"
            )
        }
        
        // 合并属性构建最终的Cat和Dog实例
        self.cat = Cat(name: catName, weight: catWeight, food: tempCat.food)
        self.dog = Dog(name: dogName, weight: dogWeight, food: tempDog.food)
    }
}

struct Dog {
    let name: String
    let weight: Int
    let food: String
}

struct Cat {
    let name: String
    let weight: Int
    let food: String
}

关键说明

  • 完整CodingKeys:必须包含catName、dogName、cat、dog四个键,才能从解码器容器中获取所有需要的解码数据。
  • 类型转换处理:JSON中weight是字符串类型,通过临时结构体先解码为字符串,再转换为Cat/Dog所需的Int类型,避免类型不匹配报错。
  • 属性合并:将顶层名称与嵌套对象的属性结合,直接构建目标结构体实例,逻辑清晰且易维护。

内容的提问来源于stack exchange,提问作者Turnipdabeets

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 18:35:16