🤮

Swift: JSONSerializationのわけわからん挙動

2021/05/18に公開

Dictionaryを通信の時にJSON文字列にエンコードして投げて、受け取ったらDictionaryにデコードするというコードを書いていたら気持ち悪い現象が起きていた。

let value: Double = 54.321
let value2: Int = 100

let dic: [String: Any] = [
    "cpuTemperature": value,
    "gpuTemperature": value2
]

guard let encodeData = try? JSONSerialization.data(withJSONObject: dic, options: [.prettyPrinted]),
      let jsonStr = String(data: encodeData, encoding: .utf8) else { exit(1) }

print(jsonStr)

guard let decodeData = jsonStr.data(using: .utf8),
   let dic2 = try? JSONSerialization.jsonObject(with: decodeData, options: []) as? [String: Any]
else { exit(2) }

print(dic2)
結果
{
  "gpuTemperature" : 100,
  "cpuTemperature" : 54.320999999999998
}
["cpuTemperature": 54.321, "gpuTemperature": 100]
Program ended with exit code: 0

JSON文字列になっている際、Doubleの値が54.320999999999998と表記されているのに、受け取ってDictionaryに戻した時は元の値に戻っている。

対策

浮動小数点数だろうが整数だろうが、とりあえずDecimalで包めばちゃんとJSONでもそのまま表現されます。

let dic: [String: Any] = [
    "cpuTemperature": Decimal(value),
    "gpuTemperature": Decimal(value2)
]
結果
{
  "cpuTemperature" : 54.321,
  "gpuTemperature" : 100
}
["cpuTemperature": 54.321, "gpuTemperature": 100]
Program ended with exit code: 0

関連

Discussion