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

Swift iOS Codable解析JSON时如何将value格式化为3位小数

问题说明
  • 接口返回JSON格式的油价数据,需要在数据模型初始化阶段完成字段格式化,要求value字段固定保留3位小数,例如原始值"2.81"需要处理为"2.810"
  • 接口返回原始JSON结构如下:
[
  {
    "name": "Diesel",
    "id": "1",
    "maj": "2022-07-06 18:28:29",
    "value": "2.81"
  },
  {
    "name": "SP95",
    "id": "5",
    "maj": "2022-07-06 18:28:29",
    "value": "2.048"
  }
]
  • 当前已定义的Codable模型如下,曾尝试结合CustomStringConvertible实现格式化但未成功,不确定方案合理性:
struct Price: Codable {
    let name: String
    let id, maj: String?
    var value: String?
    var isCheapest: Bool?
}
实现方案

CustomStringConvertible仅用于自定义实例打印、转字符串时的输出规则,不适合做解码阶段的数据清洗,不推荐用这个思路实现需求。最稳妥的方案是自定义Codable初始化方法,在解码时一次性完成字段格式化,后续使用无需重复计算。

  1. 先定义全局复用的数字格式化器,固定3位小数规则,同时避免区域设置导致的小数点符号异常:
private let priceFormatter: NumberFormatter = {
    let formatter = NumberFormatter()
    formatter.numberStyle = .decimal
    formatter.minimumFractionDigits = 3
    formatter.maximumFractionDigits = 3
    formatter.decimalSeparator = "."
    return formatter
}()
  1. 重写Price结构体的解码初始化方法,在解码value字段时完成格式化:
struct Price: Codable {
    let name: String
    let id, maj: String?
    var value: String?
    var isCheapest: Bool?
    
    enum CodingKeys: String, CodingKey {
        case name, id, maj, value, isCheapest
    }
    
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        // 解码无需特殊处理的基础字段
        name = try container.decode(String.self, forKey: .name)
        id = try container.decodeIfPresent(String.self, forKey: .id)
        maj = try container.decodeIfPresent(String.self, forKey: .maj)
        isCheapest = try container.decodeIfPresent(Bool.self, forKey: .isCheapest)
        
        // 格式化value字段
        guard let rawValueStr = try container.decodeIfPresent(String.self, forKey: .value),
              let rawNumber = Double(rawValueStr),
              let formattedValue = priceFormatter.string(from: NSNumber(value: rawNumber)) else {
            value = nil
            return
        }
        value = formattedValue
    }
}
  1. 效果验证:解码上述示例JSON后,Diesel对应的value为"2.810",SP95对应的value保持"2.048",符合预期。如果后续需要调整小数位数,仅需修改格式化器的minimumFractionDigits、maximumFractionDigits属性即可,无需改动解码逻辑。

也可以通过扩展给Price增加计算属性返回格式化后的value,但这种方案每次访问属性都会触发一次格式化计算,性能远不如初始化阶段一次性处理,仅适合临时、少量使用的场景。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 17:36:18