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

时间:2018-04-08 11:58:16

标签: json swift4 decodable swift4.1

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

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

有关如何解决此问题的任何建议?我已尝试过" Any"作为数据类型,但这不符合可解码协议

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 :(得分: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
}