Home > Software design >  Strava API returns null as first value of powerstream - Swift
Strava API returns null as first value of powerstream - Swift

Time:01-21

When trying to use the Strava API with wattages per second I keep running into the problem of the first value always being null instead of a number.

struct streamsElement: Decodable {
    struct Stream: Decodable {
      let data: [Double]?
      let series_type: String
      let original_size: Int
      let resolution: String
      
    }

//decoding
if let wattsData = streams.watts?.data {
    for watts in wattsData {
        wattsArr.append("watts: \(watts)" )
    }
}
"watts":{"data":[
null,
144,
98,
95, etc.

This works fine for all the other streams.

Error

Error decoding JSON data: valueNotFound(Swift.Double, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "watts", intValue: nil), CodingKeys(stringValue: "data", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0)], debugDescription: "Expected Double but found null value instead.", underlyingError: nil))

How can i turn this Null value into a zero so I don't get a JSON decoding error?

I tried to skip the first value in the decoding but this did not work.

CodePudding user response:

You don´t have to turn the null JSON value into a 0 just to prevent the crash. Change the the type of the array to an optional and you are good to go. E.g.:

struct Stream: Decodable {
    let data: [Double?] // add a ? if the array itself is optional too
    let series_type: String
    let original_size: Int
    let resolution: String
}

I don´t know why and where you do what you described as decoding. But if you want your data Double´s to be nonoptional you could do something like this in a custom decoder:

struct streamsElement: Decodable {
    struct Stream: Decodable {
        let data: [Double]
        
        enum CodingKeys: CodingKey{
            case data
        }
        
        init(from decoder: Decoder) throws {
            let container = try decoder.container(keyedBy: CodingKeys.self)
            // decode the data property to the array of optionals
            let data = try container.decode([Double?].self, forKey: .data)
            // replace nil values with 0
            self.data = data.map{$0 ?? 0}
        }
    }
    
    var watts: Stream
}

I´ve implemented only the problematic property. Of course you would need to expand this to the others.

  • Related