Посылая числовое значение в запросе http с помощью swift, добавляет 000000000000001 к фактическому значению

Я пытаюсь выполнить HTTP-запрос к серверу: содержимое представляет собой объект JSON, который содержит числовое значение для ключа "сумма". Если "количество" - это значение с десятичной цифрой, например, 1.6, запрос будет содержать значение 1.6000000000000001, и это значение не будет принято Сервером (API-интерфейс выполнен на Java, а тип является плавающим. Я не могу отправить Строка на сервер, так как API, который получает данные от меня, может принимать только числа для "суммы". Я пытался выполнить запрос с помощью Siesta Framework или dataTask, но результат всегда одинаков

это как я создаю запрос (я пропустил менее важные части)

let jsonData = try! JSONSerialization.data(withJSONObject: jsonObject) // jsonObject contains the Double value "amount"
let request = URLRequest(url: url)
request.httpBody = jsonData
let task = URLSession.shared.dataTask(with: request)    
task.resume()

2 ответа

Решение

Без кода, который полностью воспроизводит проблему, трудно сказать наверняка, но я представляю, что вы видите, это поведение:

let amount = 1.6  // Double
let jsonObject = ["amount": amount]
let jsonData = try! JSONSerialization.data(withJSONObject: jsonObject)
String(data: jsonData, encoding: String.Encoding.utf8)

Сериализация JSON Swift Foundation всегда форматирует числовые значения с полной точностью - поэтому число с двойной точностью 1.6 форматируется как 1.6000000000000001,

Решение 1. Отправьте строку

Вы можете и должны отправить строку, если сервер ее принимает:

let amount = "1.6"  // String
let jsonObject = ["amount": amount]
let jsonData = try! JSONSerialization.data(withJSONObject: jsonObject)
String(data: jsonData, encoding: String.Encoding.utf8)

Обратите внимание, что строка является единственным правильным способом отправки этого значения, если вы имеете дело с деньгами или чем-то еще, где точные значения имеют значение: даже если вы пишете это как 1.6стандартный синтаксический анализатор JSON, скорее всего, преобразует его в число с плавающей точкой на принимающей стороне.

Решение 2. Используйте десятичную для изменения форматирования

Если по какой-то причине вам просто нужно отформатировать его с меньшей точностью, чтобы он прошел проверку на сервере, вы можете встроить его в JSON как Decimal вместо Double и он будет отформатирован по-другому:

let amount = 1.6
let jsonObject = ["amount": Decimal(amount)]
let jsonData = try! JSONSerialization.data(withJSONObject: jsonObject)
String(data: jsonData, encoding: String.Encoding.utf8)
// {"amount":1.6}

Вы даже можете манипулировать Decimal округлить с определенной точностью.

Однако обратите внимание, что это не избавит вас от проблем точности с плавающей запятой: вы по-прежнему отправляете число с плавающей точкой в ​​соответствии со спецификацией JSON, и оно, скорее всего, будет проанализировано как число с плавающей точкой на принимающей стороне.

Не видя ваш код, сложно предложить помощь, однако, нужно проверить, используете ли вы NumberFormatter, чтобы убедиться, что вы получаете правильное округление значений. Предполагая, что вы извлекаете номер из UITextField, вам понадобится что-то вроде этого:

let numberFormatter = NumberFormatter()
numberFormatter.numberStyle = .decimal
if let textValue = textField.value {
    var amount = numberFormatter.number(from: textValue)
}
Другие вопросы по тегам