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

如何重写JSONDecoder方法解析后端返回的自定义非标准Location JSON

解析非标准JSON中的Location字段方案

遇到这种后端返回的非标准JSON确实头疼——标准JSON根本不支持(x, y)这种元组格式,所以默认的JSONDecoder直接罢工很正常。要解决这个问题,我们只需要给Location结构体自定义解码逻辑就行,下面是具体的实现方案:

核心思路

因为(54.000000, 21.000000)不符合JSON规范,所以我们不能直接让解码器把它当成一个对象解析,而是先把它当作字符串读取,再手动处理成我们需要的经纬度数值。

自定义解码的实现代码

修改你的Location结构体,添加自定义的init(from:)方法,同时可以按需添加编码逻辑(如果需要把对象转回后端要求的非标准格式的话):

struct Location: Codable {
    var latitude: Double
    var longitude: Double
    
    // 自定义解码逻辑
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        // 先把location字段按字符串取出
        let locationString = try container.decode(String.self, forKey: .location)
        
        // 清理字符串:去掉前后的括号,按逗号分割并去除空格
        let cleanedString = locationString.trimmingCharacters(in: CharacterSet(charactersIn: "()"))
        let coordinateComponents = cleanedString.split(separator: ",")
            .map { $0.trimmingCharacters(in: .whitespaces) }
        
        // 验证格式是否合法
        guard coordinateComponents.count == 2,
              let lat = Double(coordinateComponents[0]),
              let lon = Double(coordinateComponents[1]) else {
            throw DecodingError.dataCorruptedError(
                forKey: .location,
                in: container,
                debugDescription: "Location格式不符合预期,无法解析为经纬度"
            )
        }
        
        latitude = lat
        longitude = lon
    }
    
    // 可选:如果需要将Location转回后端要求的非标准格式,添加自定义编码
    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        let locationString = "(\(latitude), \(longitude))"
        try container.encode(locationString, forKey: .location)
    }
    
    // 定义编码键
    enum CodingKeys: String, CodingKey {
        case location
    }
}

测试解码效果

用你原来的测试代码试试,现在应该能正常解析了:

let json = """
{ "location": (54.000000, 21.000000) }
"""
let dataJson = json.data(using: .utf8)!
do {
    let location = try JSONDecoder().decode(Location.self, from: dataJson)
    print("解析成功:纬度\(location.latitude),经度\(location.longitude)")
} catch {
    print("解码失败:\(error)")
}

备选方案:预处理JSON字符串

如果你的JSON结构很简单,也可以先把字符串里的(替换成",)替换成",让(x,y)变成"x,y",不过这种方法风险较高——如果JSON里其他地方也有括号(比如字符串内容里),就会破坏原有结构,所以更推荐上面的自定义解码方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:29:21