首页 文章

可解码和JSON,相同变量的2种数据类型

提问于
浏览
1

我正在使用Decodable协议解码一些json,但我遇到了一个问题:

我得到了一个答案,如果没有地理位置数据添加到元素,经度和纬度可以是整数(纬度= 0),如果有地理数据,则可以是字符串(fx . 纬度=“25.047880”)可用 . 现在,当我解码json时,我不知道如何构建我的Struct,因为long和lat不能同时是String和Int ..所以当获取表示两种情况的元素时,我得到解码错误 .

有关如何解决这个问题的任何建议?我尝试使用“Any”作为数据类型,但这不符合Decodable协议

struct JPhoto: Decodable {
  let id: String
  let farm: Int
  let secret: String
  let server: String
  let owner: String
  let title: String
  let latitude: String //Can both be Int and String
  let longitude: String //Can both be Int and String
}

1 回答

  • 0

    您需要编写自己的编码器/解码器 . 您可以使用关联的值枚举来执行此操作,使用switch语句进行编码以及要解码的throw / catch行为:

    enum AngularDistance:Codable {
        case string(String), integer(Int)
    
        func encode(to encoder: Encoder) throws {
            switch self {
            case .string(let str):
                var container = encoder.singleValueContainer()
                try container.encode(str)
            case .integer(let int):
                var container = encoder.singleValueContainer()
                try container.encode(int)
            }
        }
    
        init(from decoder: Decoder) throws {
            do {
                let container = try decoder.singleValueContainer()
                let str = try container.decode(String.self)
                self = AngularDistance.string(str)
            }
            catch {
                  do { let container = try decoder.singleValueContainer()
                       let int = try container.decode(Int.self)
                       self = AngularDistance.integer(int) 
                  }
                  catch {
                       throw DecodingError.typeMismatch(AngularDistance.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Expected to decode an Int or a String"))
                  }
            }
        }
    }
    

    以下是编码和解码此 AngularDistance 类型的示例:

    let lat = [AngularDistance.string("String"), AngularDistance.integer(10)]
    let encoder = JSONEncoder()
    var decoder = JSONDecoder()
    
    do {
        let encoded = try encoder.encode(lat)
        try decoder.decode(Array<AngularDistance>.self, from: encoded)
    }
    catch DecodingError.typeMismatch(let t, let e)  {
        t
        e.codingPath
        e.debugDescription
    }
    catch {
        print(error.localizedDescription)
        }
    

    这是你的结构重写:

    struct JPhoto: Decodable {
      let id: String
      let farm: Int
      let secret: String
      let server: String
      let owner: String
      let title: String
      let latitude: AngularDistance //Can both be Int and String
      let longitude: AngularDistance //Can both be Int and String
    }
    

相关问题