Home > Software engineering >  How do I create a decodable struct to match JSON nest from API?
How do I create a decodable struct to match JSON nest from API?

Time:08-05

I am trying to create a decodable struct that will store select data from an API called MarketStack. The API uses JSON format and nests the information I am looking for like this.

{
"pagination": {
    "limit": 100,
    "offset": 0,
    "count": 100,
    "total": 9944
},
"data": [
    {
        "open": 129.8,
        "high": 133.04,
        "low": 129.47,
        "close": 132.995,
        "volume": 106686703.0,
        "adj_high": 133.04,
        "adj_low": 129.47,
        "adj_close": 132.995,
        "adj_open": 129.8,
        "adj_volume": 106686703.0,
        "split_factor": 1.0,
        "dividend": 0.0,
        "symbol": "AAPL",
        "exchange": "XNAS",
        "date": "2021-04-09T00:00:00 0000"
        },
        [...]
]

}

My struct currently looks like this.

struct ScrapeStruct: Decodable {
var high: Double
var low: Double
}

But I am worried that this won't access the right response objects because they are nested in "data". I thought I could maybe do something like this.

struct ScrapeStruct: Decodable {
var data: high
var data: low
}

Like I've seen online but still just get errors about it not following Decodable format. Any help or suggestions to research would be greatly appreciated. Thanks!

CodePudding user response:

There are a couple of issues. Firstly, your JSON data is an array of objects and your struct is just an object. So, first create a struct to model each object. Also, using var in structs is not very useful considering structs have to be destroyed and recreated with a changed property to be modified (energy intensive process). It should look like this:


struct SingleData: Codable {
     let open: Double 
     let high: Double
}

Now, ScrapeStruct should have a property called data that should be an array of SingleData. It should look like this:

struct ScrapeStruct: Decodable {
     let data: [SingleData]
}

Now, as for your second struct. It will not work because "high" and "low" are types that do not exist. To parse (essentially converting languages, in this case JSON to Swift) you can only use basic types or objects created with basic types (such as Date, Int, String, Double, etc)

struct ScrapeStruct: Decodable {
var data: high //type high does not exist
var data: low  //type low does not exist
}

CodePudding user response:

If you want to avoid manual decoding and rely on synthesized Decodable implementation, your data structures should entirely match responses.

Your example is long, but for instance, for this shortened response of the similar structure:

{
  "data" : [
    {
      "open" : 129.8,
      "high" : 133.04
    },
    {
      "open" : 123.4,
      "high" : 567.8
    }
  ]
}

This should work:

struct Response: Decodable {
  struct Scrape: Decodable {
    let open: Double
    let high: Double
  }
  let data: [Scrape]
}
  • Related