【问题标题】:Deal with an API that changes format处理改变格式的 API
【发布时间】:2021-02-16 03:00:38
【问题描述】:

寻求一些建议。 我正在利用 WordsAPI 使用 swift 创建一个拼写检查器 iOS 应用程序,但是,根据您搜索的词,JSON 响应有时会采用不同的格式。

对“测试”这个词的反应看起来像这样(我已经去掉了大部分内容,只是为了让大家明白这一点)

{ 
    "word": "test", 
    "pronunciation": {
         "all": "tɛst"
    }
}

而“测试”一词的响应看起来像这样

{ 
    "word": "testing", 
    "pronunciation": "'tɛstɪŋ" 
}

我正在使用模型来解码响应数据

struct WordDetails: Codable {
   let word: String
   let results: [Definition]
   let pronunciation: Pronounce
}

struct Pronounce: Codable {
   let all: String
}

struct Definition: Codable {
   let definition: String
   let partOfSpeech: String
   let synonyms: [String]?
}

但这只会处理一种情况而无法解码另一种情况。我可以用这种方式来处理这两种格式吗?

【问题讨论】:

    标签: ios json swift api codable


    【解决方案1】:

    您可以自己实现解码并尝试将发音键解码为String类型。如果失败并出现DecodingError.typeMismatch 错误,则将其解码为Pronounce 类型:

    struct WordDetails: Codable {
        let word: String
        let results: [Definition]
        let pronunciation: Pronounce
        
        enum CodingKeys: String, CodingKey {
            case word
            case results
            case pronunciation
        }
        
        init(from decoder: Decoder) throws {
            let container = try decoder.container(keyedBy: CodingKeys.self)
            word = try container.decode(String.self, forKey: .word)
            results = try container.decode([Definition].self, forKey: .results)
            do {
                let string = try container.decode(String.self, forKey: .pronunciation)
                pronunciation = Pronounce(all: string)
            } catch DecodingError.typeMismatch {
                pronunciation = try container.decode(Pronounce.self, forKey: .pronunciation)
            }
        }
    }
    

    【讨论】:

    • 这很好用。但是,我还需要创建一个部分为空的 WordDetail 对象(仅包含单词),然后在稍后阶段从 API 更新详细信息。这还能用吗?
    • @jdez 如果您将所有不需要的属性更改为可选类型或给它们默认值,您可以创建一个部分空的WordDetail 对象。我不知道哪种方法最适合您的情况。
    • 我创建了第二个初始化,它只接受一个参数,其他所有参数都有默认值。我认为这行得通。感谢您的帮助。
    【解决方案2】:

    您可以创建一个枚举并手动解码响应。

    struct WordDetails: Codable {
       let word: String
       let results: [Definition]
       let pronunciation: PronounceResult
    }
    
    struct Pronounce: Codable {
       let all: String
    }
    
    enum PronounceResult: Decodable {
        case string(String)
        case object(Pronounce)
    
        public init(from decoder: Decoder) throws {
            let container = try decoder.singleValueContainer()
            if let string = try? container.decode(String.self) {
                self = .string(string)
                return
             }
             
             if let pronounce = try? container.decode(Pronounce.self) {
                 self = .object(pronounce)
                 return
             }
             let context = DecodingError.Context(codingPath: decoder.codingPath,
                                                        debugDescription: "Wrong type")
             throw DecodingError.typeMismatch(Value.self, context)
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2020-04-29
      • 2023-03-16
      • 2022-01-16
      • 1970-01-01
      • 1970-01-01
      • 2022-10-13
      • 1970-01-01
      • 1970-01-01
      • 2011-06-12
      相关资源
      最近更新 更多