Swift: JSON Decode fails in some cases - json

I have this struct
struct ProductInfo: Codable {
var code: String
var product_name: String?
var status: Int
enum CodingKeys: String, CodingKey {
case code
case product
case status
enum ProductCodingKeys: String, CodingKey {
case product_name
}
}
init(from decoder: Decoder) throws {
let rootContainer = try! decoder.container(keyedBy: CodingKeys.self)
let productContainer = try! rootContainer.nestedContainer(keyedBy: CodingKeys.ProductCodingKeys.self, forKey: .product)
product_name = try! productContainer.decode(String.self, forKey: .product_name)
code = try! rootContainer.decode(String.self, forKey: .code)
status = try! rootContainer.decode(Int.self, forKey: .status)
}
func encode(to encoder: Encoder) throws {
var rootContainer = encoder.container(keyedBy: CodingKeys.self)
var productContainer = rootContainer.nestedContainer(keyedBy: CodingKeys.ProductCodingKeys.self, forKey: .product)
try rootContainer.encode(code, forKey: .code)
try rootContainer.encode(status, forKey: .status)
try productContainer.encode(product_name, forKey: .product_name)
}
}
Problem is that is the product is not found on the DB, the CodingKey "product" will not exist, only code and status are available.
That means, this line
let productContainer = try! rootContainer.nestedContainer(keyedBy: CodingKeys.ProductCodingKeys.self, forKey: .product)
Will fail because the key is not found in the JSON Response.
My idea was to check the status value (which I have in the Response) but it seems not working
Thanks

You can use contains(_:):
if rootContainer.contains(.product) {
let productContainer = try rootContainer.nestedContainer(keyedBy: CodingKeys.ProductCodingKeys.self, forKey: .product)
product_name = try productContainer.decode(String.self, forKey: .product_name)
}
To test it:
let jsonStr = """
[
{
"code": "8001620004159",
"product": { "_id": "8001620004159", "product_name": "The San Benedetto" },
"status": 1,
"status_verbose": "product found"
},
{
"code": "4007843212122",
"status": 0,
"status_verbose": "product not found"
}
]
"""
let jsonData = Data(jsonStr.utf8)
do {
let decoder = JSONDecoder()
let items = try decoder.decode([ProductInfo].self, from: jsonData)
print(items)
} catch {
print("Error: \(error)")
}
Side note:
I'd avoid try! and replace them with try since the method throws already.

Related

Parsing Json from Web API

Hello my name is Nico,
I am a complete beginner in App programming/SwiftUI.
I am trying to parse json data from an web api but somehow I cannot parse the data correctly. I assume that my json structure is not correct but I cannot find the problem.
The Json which I get from the Web API looks something like this:
{
"pois": [
{
"id": "2635094451",
"lat": "52.410150",
"lat_s": "52.4",
"lng": "10.776630",
"lng_s": "10.8",
"street": "Röntgenstraße",
"content": "8137285512",
"backend": "0-239283152",
"type": "1",
"vmax": "50",
"counter": "0",
"create_date": "2021-11-18 13:21:50",
"confirm_date": "2021-11-18 13:21:43",
"gps_status": "-",
"info": " {\"qltyCountryRoad\":1,\"confirmed\":\"0\",\"gesperrt\":\"0\",\"precheck\":\"[Q1|21|0]\"}",
"polyline": ""
}
],
"grid": []
}
My Structure looks like this:
struct APIResponse: Codable {
let pois: [InputDataPois]
let grid: [InputDataGrid]
private enum CodingKeys: String, CodingKey {
case pois
case grid
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.pois = try container.decode(APIResponse.self, forKey: .pois).pois
self.grid = try container.decode(APIResponse.self, forKey: .grid).grid
}
}
struct InputDataPois: Codable, Identifiable {
let id:String
let lat:String
let lat_s:String
let lng:String
let lng_s:String
let street:String
let content:String
let backend:String
let type:String
let vmax:String
let counter:String
let create_date:String
let confirm_date:String
let gps_status:String
let info:String
let polyline:String
}
extension InputDataPois {
private enum CodingKeys: String, CodingKey {
case id
case lat
case lat_s
case lng
case lng_s
case street
case content
case backend
case type
case vmax
case counter
case create_date
case confirm_date
case gps_status
case info
case polyline
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.id = try container.decode(String.self, forKey: .id)
self.lat = try container.decode(String.self, forKey: .lat)
self.lat_s = try container.decode(String.self, forKey: .lat_s)
self.lng = try container.decode(String.self, forKey: .lng)
self.lng_s = try container.decode(String.self, forKey: .lng_s)
self.street = try container.decode(String.self, forKey: .street)
self.content = try container.decode(String.self, forKey: .content)
self.backend = try container.decode(String.self, forKey: .backend)
self.type = try container.decode(String.self, forKey: .type)
self.vmax = try container.decode(String.self, forKey: .vmax)
self.counter = try container.decode(String.self, forKey: .counter)
self.create_date = try container.decode(String.self, forKey: .create_date)
self.confirm_date = try container.decode(String.self, forKey: .confirm_date)
self.gps_status = try container.decode(String.self, forKey: .gps_status)
self.info = try container.decode(String.self, forKey: .info)
self.polyline = try container.decode(String.self, forKey: .polyline)
}
}
struct InputDataGrid: Codable {
}
and my Bundle like this:
extension Bundle {
func decode(_ file: String) -> [InputDataPois] {
// 1. Locate the Json File
guard let url = URL(string: file) else {
fatalError("Failed to locate \(file) in bundle")
}
// 2.Create a property for the Data
guard let data = try? Data(contentsOf: url) else {
fatalError("Failed to Load \(file) from bundle.")
}
// 3. Create a property for the data
let str = String(decoding: data, as: UTF8.self)
print("\(str)")
guard let loaded = try? JSONDecoder().decode(APIResponse.self, from: data).pois else {
fatalError("Failed to decode \(file) from bundle.")
}
// 4. Return the ready-to-use data
return loaded
}
}
And In my View I am using:
let speed: [InputDataPois] = Bundle.main.decode("https://cdn2.atudo.net/api/1.0/vl.php?type=0,1,2,3,4,5,6&box=52.36176390234046,10.588760375976562,52.466468685912744,11.159706115722656")
The error I am getting looks something like this.
ErrorMessage
ConsoleError
Thanks in advance for you help.
Remove your custom Codable implementation and coding keys. They are not necessary, the compiler can generate them for you with this simple JSON. Then everything should work.
The problem here specifically is your APIResponse decoding:
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.pois = try container.decode(APIResponse.self, forKey: .pois).pois
self.grid = try container.decode(APIResponse.self, forKey: .grid).grid
}
To decode an APIResponse you try to decode two APIResponses. This again would try to decode APIResponse leading to endless recursion. The only reason you are not seeing that is that your JSON contains arrays making the second call to container(keyedBy:) fail. Try setting a breakpoint (or if you must a print statement) on the first line of your init(from:) and you will see that this is called a second time before it fails.
To fix that you would need to decode the actual type of your properties:
self.pois = try container.decode([InputDataPois].self, forKey: .pois)
But as I said, there is nothing in your JSON format requiring manually implementing the decoder, so the best is to let the compiler synthesize it for you.

swift decode polymorphic json response

Hello i want to decode this json.
"interest_point":{
"id": 2,
"name": "Panoramic",
"description": "On vous propose ....",
"pointable_type": "ConferenceInterestPoint",
"pointable_id": 1,
"working_time": [],
"pointable": {
"id": 1,
"surface": 354.56,
"capacity": "140",
"price": 500,
"price_unit": "HOURS",
},
"comments": [],
}
"interest_point":{
"id": 5,
"name": "Carte",
"description": "XXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"pointable_type": "RestaurantInterestPoint",
"pointable_id": 2,
"working_time": [],
"pointable": {
"id": 2,
"type": "CARTE",
"smocking_area": 1,
},
"comments": []
}
the "pointable" field is a child class of interest_point with the type depend on "pointable_type".I want to dynamicaly decode response into the good ChildType of InterestPoint
Perhaps you have the following class describing the root of your JSON:
final class Root: Codable {
let interestPoint: InterestPoint?
private enum CodingKeys: String, CodingKey {
case interestPoint = "interest_point"
}
required init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
interestPoint = try values.decodeIfPresent(InterestPoint.self, forKey: .interestPoint)
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(interestPoint, forKey: .interestPoint)
}
}
As I can guess you have BaseInterestPoint that serves as a base class for InterestPoint, ConferenceInterestPoint and RestaurantInterestPoint:
class BaseInterestPoint: Codable {
let id: Int?
private enum CodingKeys: String, CodingKey {
case id
}
required init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
id = try values.decodeIfPresent(Int.self, forKey: .id)
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(id, forKey: .id)
}
}
ConferenceInterestPoint and RestaurantInterestPoint:
final class ConferenceInterestPoint: BaseInterestPoint {
let surface: Double?
let capacity: String?
let price: Int?
let priceUnit: String?
private enum CodingKeys: String, CodingKey {
case surface
case capacity
case price
case priceUnit = "price_unit"
}
required init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
surface = try values.decodeIfPresent(Double.self, forKey: .surface)
capacity = try values.decodeIfPresent(String.self, forKey: .capacity)
price = try values.decodeIfPresent(Int.self, forKey: .price)
priceUnit = try values.decodeIfPresent(String.self, forKey: .priceUnit)
try super.init(from: decoder)
}
override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(surface, forKey: .surface)
try container.encode(capacity, forKey: .capacity)
try container.encode(price, forKey: .price)
try container.encode(priceUnit, forKey: .priceUnit)
}
}
final class RestaurantInterestPoint: BaseInterestPoint {
let type: String?
let smockingArea: Int?
private enum CodingKeys: String, CodingKey {
case type
case smockingArea = "smocking_area"
}
required init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
type = try values.decodeIfPresent(String.self, forKey: .type)
smockingArea = try values.decodeIfPresent(Int.self, forKey: .smockingArea)
try super.init(from: decoder)
}
override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(type, forKey: .type)
try container.encode(smockingArea, forKey: .smockingArea)
}
}
To solve the problem with polymorphic objects use enum:
enum Pointable {
case conferenceInterestPoint(ConferenceInterestPoint?)
case restaurantInterestPoint(RestaurantInterestPoint?)
}
In such case you will get the following InterestPoint:
final class InterestPoint: BaseInterestPoint {
let name: String?
let description: String?
let pointableType: String?
let pointableId: Int?
let workingTime: [Int]?
let pointable: Pointable?
let comments: [String]?
private enum CodingKeys: String, CodingKey {
case name
case description
case pointableType = "pointable_type"
case pointableId = "pointable_id"
case workingTime = "working_time"
case pointable
case comments
}
required init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
name = try values.decodeIfPresent(String.self, forKey: .name)
description = try values.decodeIfPresent(String.self, forKey: .description)
pointableType = try values.decodeIfPresent(String.self, forKey: .pointableType)
pointableId = try values.decodeIfPresent(Int.self, forKey: .pointableId)
workingTime = try values.decodeIfPresent([Int].self, forKey: .workingTime)
if pointableType == "ConferenceInterestPoint" {
pointable = .conferenceInterestPoint(try values.decodeIfPresent(ConferenceInterestPoint.self, forKey: .pointable))
} else if pointableType == "RestaurantInterestPoint" {
pointable = .restaurantInterestPoint(try values.decodeIfPresent(RestaurantInterestPoint.self, forKey: .pointable))
} else {
pointable = nil
}
comments = try values.decodeIfPresent([String].self, forKey: .comments)
try super.init(from: decoder)
}
override func encode(to encoder: Encoder) throws {
try super.encode(to: encoder)
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(name, forKey: .name)
try container.encode(description, forKey: .description)
try container.encode(pointableType, forKey: .pointableType)
try container.encode(pointableId, forKey: .pointableId)
try container.encode(workingTime, forKey: .workingTime)
if let pointable = pointable {
switch pointable {
case .conferenceInterestPoint(let conferenceInterestPoint):
if let conferenceInterestPoint = conferenceInterestPoint {
try container.encode(conferenceInterestPoint, forKey: .pointable)
}
case .restaurantInterestPoint(let restaurantInterestPoint):
if let restaurantInterestPoint = restaurantInterestPoint {
try container.encode(restaurantInterestPoint, forKey: .pointable)
}
}
}
try container.encode(comments, forKey: .comments)
}
}
All code in this post was tested in Xcode 10.2.1.

Parsing JSON with wildcard keys

I'm parsing a poorly designed JSON structure in which I can expect to find values being reused as keys pointing to further data. Something like this
{"modificationDate" : "..."
"type" : "...",
"version" : 2,
"manufacturer": "<WILDCARD-ID>"
"<WILDCARD-ID>": { /* known structure */ } }
WILDCARD-ID can be just about anything at runtime, so I can't map it to a field in a struct somewhere at compile time. But once I dereference that field, its value has known structure, at which point I can follow the usual procedure for mapping JSON to structs.
I've found myself going down this path
let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String: Any]
let manDict = json["manufacturer"]
let data = NSKeyedArchiver.archivedData(withRootObject: manDict)
// now you have data!
but this seems very circuitous, which makes me think that maybe there's a cleaner way of accomplishing this?
You can use custom keys with Decodable, like so:
let json = """
{
"modificationDate" : "...",
"type" : "...",
"version" : 2,
"manufacturer": "<WILDCARD-ID>",
"<WILDCARD-ID>": {
"foo": 1
}
}
""".data(using: .utf8)!
struct InnerStruct: Decodable { // just as an example
let foo: Int
}
struct Example: Decodable {
let modificationDate: String
let type: String
let version: Int
let manufacturer: String
let innerData: [String: InnerStruct]
enum CodingKeys: String, CodingKey {
case modificationDate, type, version, manufacturer
}
struct CustomKey: CodingKey {
var stringValue: String
var intValue: Int?
init?(stringValue: String) {
self.stringValue = stringValue
}
init?(intValue: Int) {
self.stringValue = "\(intValue)";
self.intValue = intValue
}
}
init(from decoder: Decoder) throws {
// extract all known properties
let container = try decoder.container(keyedBy: CodingKeys.self)
self.modificationDate = try container.decode(String.self, forKey: .modificationDate)
self.type = try container.decode(String.self, forKey: .type)
self.version = try container.decode(Int.self, forKey: .version)
self.manufacturer = try container.decode(String.self, forKey: .manufacturer)
// get the inner structs with the unknown key(s)
var inner = [String: InnerStruct]()
let customContainer = try decoder.container(keyedBy: CustomKey.self)
for key in customContainer.allKeys {
if let innerValue = try? customContainer.decode(InnerStruct.self, forKey: key) {
inner[key.stringValue] = innerValue
}
}
self.innerData = inner
}
}
do {
let example = try JSONDecoder().decode(Example.self, from: json)
print(example)
}
You can capture the idea of "a specific, but currently unknown key" in a struct:
struct StringKey: CodingKey {
static let modificationDate = StringKey("modificationDate")
static let type = StringKey("type")
static let version = StringKey("version")
static let manufacturer = StringKey("manufacturer")
var stringValue: String
var intValue: Int?
init?(stringValue: String) { self.init(stringValue) }
init?(intValue: Int) { return nil }
init(_ stringValue: String) { self.stringValue = stringValue }
}
With that, decoding is straightforward, and only decodes the structure that matches the key:
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: StringKey.self)
modificationDate = try container.decode(String.self, forKey: .modificationDate)
type = try container.decode(String.self, forKey: .type)
version = try container.decode(Int.self, forKey: .version)
manufacturer = try container.decode(String.self, forKey: .manufacturer)
// Decode the specific key that was identified by `manufacturer`,
// and fail if it's missing
manufacturerData = try container.decode(ManufacturerData.self,
forKey: StringKey(manufacturer))
}

Decoding two different JSON responses in one model class using Codable

Based on the requirement I got two different kinds of response from api. That is
{
"shopname":"xxx",
"quantity":4,
"id":1,
"price":200.00,
}
another response
{
"storename":"xxx",
"qty":4,
"id":1,
"amount":200.00,
}
Here both json values are decoding in same model class. Kindly help me to resolve this concern.
is it is possible to set value in single variable like qty and quantity both are stored in same variable based on key param availability
Here's an approach that lets you have only one property in your code, instead of two Optionals:
Define a struct that contains all the properties you need, with the names that you'd like to use in your code. Then, define two CodingKey enums that map those properties to the two different JSON formats and implement a custom initializer:
let json1 = """
{
"shopname":"xxx",
"quantity":4,
"id":1,
"price":200.00,
}
""".data(using: .utf8)!
let json2 = """
{
"storename":"xxx",
"qty":4,
"id":1,
"amount":200.00,
}
""".data(using: .utf8)!
struct DecodingError: Error {}
struct Model: Decodable {
let storename: String
let quantity: Int
let id: Int
let price: Double
enum CodingKeys1: String, CodingKey {
case storename = "shopname"
case quantity
case id
case price
}
enum CodingKeys2: String, CodingKey {
case storename
case quantity = "qty"
case id
case price = "amount"
}
init(from decoder: Decoder) throws {
let container1 = try decoder.container(keyedBy: CodingKeys1.self)
let container2 = try decoder.container(keyedBy: CodingKeys2.self)
if let storename = try container1.decodeIfPresent(String.self, forKey: CodingKeys1.storename) {
self.storename = storename
self.quantity = try container1.decode(Int.self, forKey: CodingKeys1.quantity)
self.id = try container1.decode(Int.self, forKey: CodingKeys1.id)
self.price = try container1.decode(Double.self, forKey: CodingKeys1.price)
} else if let storename = try container2.decodeIfPresent(String.self, forKey: CodingKeys2.storename) {
self.storename = storename
self.quantity = try container2.decode(Int.self, forKey: CodingKeys2.quantity)
self.id = try container2.decode(Int.self, forKey: CodingKeys2.id)
self.price = try container2.decode(Double.self, forKey: CodingKeys2.price)
} else {
throw DecodingError()
}
}
}
do {
let j1 = try JSONDecoder().decode(Model.self, from: json1)
print(j1)
let j2 = try JSONDecoder().decode(Model.self, from: json2)
print(j2)
} catch {
print(error)
}
Handling different key names in single model
Below are two sample json(dictionaries) that have some common keys (one, two) and a few different keys (which serve the same purpose of error).
Sample json:
let error_json:[String: Any] = [
"error_code": 404, //different
"error_message": "file not found", //different
"one":1, //common
"two":2 //common
]
let failure_json:[String: Any] = [
"failure_code": 404, //different
"failure_message": "file not found", //different
"one":1, //common
"two":2 //common
]
CommonModel
struct CommonModel : Decodable {
var code: Int?
var message: String?
var one:Int //common
var two:Int? //common
private enum CodingKeys: String, CodingKey{ //common
case one, two
}
private enum Error_CodingKeys : String, CodingKey {
case code = "error_code", message = "error_message"
}
private enum Failure_CodingKeys : String, CodingKey {
case code = "failure_code", message = "failure_message"
}
init(from decoder: Decoder) throws {
let commonValues = try decoder.container(keyedBy: CodingKeys.self)
let errors = try decoder.container(keyedBy: Error_CodingKeys.self)
let failures = try decoder.container(keyedBy: Failure_CodingKeys.self)
///common
self.one = try commonValues.decodeIfPresent(Int.self, forKey: .one)!
self.two = try commonValues.decodeIfPresent(Int.self, forKey: .two)
/// different
if errors.allKeys.count > 0{
self.code = try errors.decodeIfPresent(Int.self, forKey: .code)
self.message = try errors.decodeIfPresent(String.self, forKey: .message)
}
if failures.allKeys.count > 0{
self.code = try failures.decodeIfPresent(Int.self, forKey: .code)
self.message = try failures.decodeIfPresent(String.self, forKey: .message)
}
}
}
Below extension will help you to convert your dictionary to data.
public extension Decodable {
init(from: Any) throws {
let data = try JSONSerialization.data(withJSONObject: from, options: .prettyPrinted)
let decoder = JSONDecoder()
self = try decoder.decode(Self.self, from: data)
}
}
Testing
public func Test_codeble(){
do {
let err_obj = try CommonModel(from: error_json)
print(err_obj)
let failed_obj = try CommonModel(from: failure_json)
print(failed_obj)
}catch let error {
print(error.localizedDescription)
}
}
Use like
struct modelClass : Codable {
let amount : Float?
let id : Int?
let price : Float?
let qty : Int?
let quantity : Int?
let shopname : String?
let storename : String?
enum CodingKeys: String, CodingKey {
case amount = "amount"
case id = "id"
case price = "price"
case qty = "qty"
case quantity = "quantity"
case shopname = "shopname"
case storename = "storename"
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
amount = try values.decodeIfPresent(Float.self, forKey: .amount)
id = try values.decodeIfPresent(Int.self, forKey: .id)
price = try values.decodeIfPresent(Float.self, forKey: .price)
qty = try values.decodeIfPresent(Int.self, forKey: .qty)
quantity = try values.decodeIfPresent(Int.self, forKey: .quantity)
shopname = try values.decodeIfPresent(String.self, forKey: .shopname)
storename = try values.decodeIfPresent(String.self, forKey: .storename)
}
}

Swift Decoding nested JSON

I have a problem with parsing data from NBP api "http://api.nbp.pl/api/exchangerates/tables/a/?format=json" . I created struct CurrencyDataStore and Currency
struct CurrencyDataStore: Codable {
var table: String
var no : String
var rates: [Currency]
enum CodingKeys: String, CodingKey {
case table
case no
case rates
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
table = ((try values.decodeIfPresent(String.self, forKey: .table)))!
no = (try values.decodeIfPresent(String.self, forKey: .no))!
rates = (try values.decodeIfPresent([Currency].self, forKey: .rates))!
} }
struct Currency: Codable {
var currency: String
var code: String
var mid: Double
enum CodingKeys: String, CodingKey {
case currency
case code
case mid
}
init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
currency = try values.decode(String.self, forKey: .currency)
code = try values.decode(String.self, forKey: .code)
mid = try values.decode(Double.self, forKey: .mid)
}
}
In controllerView class I wrote 2 methods to parse data from API
func getLatestRates(){
guard let currencyUrl = URL(string: nbpApiUrl) else {
return
}
let request = URLRequest(url: currencyUrl)
let task = URLSession.shared.dataTask(with: request, completionHandler: { (data, response, error) -> Void in
if let error = error {
print(error)
return
}
if let data = data {
self.currencies = self.parseJsonData(data: data)
}
})
task.resume()
}
func parseJsonData(data: Data) -> [Currency] {
let decoder = JSONDecoder()
do{
let currencies = try decoder.decode([String:CurrencyDataStore].self, from: data)
}
catch {
print(error)
}
return currencies
}
This code didn't work. I have this error "typeMismatch(Swift.Dictionary, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode Dictionary but found an array instead.", underlyingError: nil))".
Could you help me?
The JSON being returned by that API gives you an array, not a dictionary, but you're telling the JSONDecoder to expect a dictionary type. Change that line to:
let currencies = try decoder.decode([CurrencyDataStore].self, from: data)