Reputation: 559
I want to modify the value of roomTotal key while mapping. Please refer following code:
struct TransactionInfoModel: Codable {
var currencyCode: String
var total: Double
var roomCurrencyCode: String
var exchangeRate: Double
var roomTotal: Double {
get {
let y = (self.roomTotal*100).rounded()/100
return y
}
}
}
Initially, roomTotal key having the value from the server like "427.3000000002" but I want while mapping it stores value "427.3". Above code is not working.
Looking for some suggestions to resolve the issue.
Upvotes: 2
Views: 921
Reputation: 437432
See this answer for example of how to round Double
values and return a Decimal
value that will preserve the rounding, without any of the artifacts that result when trying to represent decimal values in binary floating point representations. Then, you can get the rounded Decimal
value like so:
let roomTotal = 427.3000000002
let value = roomTotal.roundedDecimal(to: 2)
And if you want to display it with a specified number of decimal places (as well as localize the string for the user's current locale), you can use a NumberFormatter
:
let formatter = NumberFormatter()
formatter.maximumFractionDigits = 2
formatter.minimumFractionDigits = 2
if let string = formatter.string(for: value) {
print(string)
}
Now, if you want the JSONDecoder
to do this conversion for you, you can, but I might be inclined to have the struct
accurately represent what was returned, avoid any convoluted init(from:)
implementation, but perhaps include a computed property to return the value in the format you want, e.g.:
struct TransactionInfoModel: Codable {
var currencyCode: String
var total: Double
var roomCurrencyCode: String
var exchangeRate: Double
var roomTotal: Double
var roundedRoomTotal: Decimal {
return roomTotal.roundedDecimal(to: 2)
}
}
If you need to round the roomTotal
when you decode it, you can write an init(from:)
to do that:
struct TransactionInfoModel: Codable {
var currencyCode: String
var total: Double
var roomCurrencyCode: String
var exchangeRate: Double
var roomTotal: Decimal
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
currencyCode = try values.decode(String.self, forKey: .currencyCode)
total = try values.decode(Double.self, forKey: .total)
roomCurrencyCode = try values.decode(String.self, forKey: .roomCurrencyCode)
exchangeRate = try values.decode(Double.self, forKey: .exchangeRate)
roomTotal = try values.decode(Double.self, forKey: .roomTotal).roundedDecimal(to: 2)
}
}
Alternatively, you could omit the init(from:)
, but manually round it after parsing:
struct TransactionInfoModel: Codable {
var currencyCode: String
var total: Double
var roomCurrencyCode: String
var exchangeRate: Double
var roomTotal: Decimal
}
And:
var object = try! JSONDecoder().decode(TransactionInfoModel.self, from: data)
var rounded = Decimal()
NSDecimalRound(&rounded, &object.roomTotal, 2, .plain)
object.roomTotal = rounded
Upvotes: 1