UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

JSON Decode with hyphens

Forums > SwiftUI

Does anybody have a clue how to decode a JSON file if some of the parameters have hyphens in them

{
      "id": 1937529874,
      "upload-time": "2008-10-13",
      "polar-user": "Matthew"

    }

Using examples from moonshot project to create a codable structure like this

struct Exercise: Codable, Identifiable  {
    let id: Int
    let upload-time: Date?
    let polar-user: String
}

I get the error "Consecutive declarations on a line must be separated by ';'" I gues it thinks its a minus sign

2      

From what i have read, hyphens should not be used in javascript notation. Like a lot of programming languages they can only contain certain characters. One of them is Swift and thats why you are getting that error. You cannot declare variable with the character '-'. The json file might be a typo so I would probably just modify the json file property to read uploadTime and go from there. I dare say that most json files you will be getting wont have hyphen in the names so you shouldn't come across it again.

Dave

2      

Thank you for the reply. The JSON comes from a web API for Polar (heartrate monitors etc.) as an example response and is full of hyphens. https://www.polar.com/accesslink-api/#get-exercise

2      

Hacking with Swift is sponsored by Essential Developer

SPONSORED Join a FREE crash course for mid/senior iOS devs who want to achieve an expert level of technical and practical skills – it’s the fast track to being a complete senior developer! Hurry up because it'll be available only until April 28th.

Click to save your free spot now

Sponsor Hacking with Swift and reach the world's largest Swift community!

You have to use a CodingKeys enum to handle member names like that.

Try this in a playground:

import UIKit

let json = """
{
"id": 1937529874,
"upload-time": "2008-10-13",
"polar-user": "Matthew"
}
""".data(using: .utf8)!

struct Exercise: Codable, Identifiable {
    var id: Int
    var uploadTime: Date?
    var polarUser: String

    enum CodingKeys: String, CodingKey {
        case id
        case uploadTime = "upload-time"
        case polarUser = "polar-user"
    }
}

let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd"

let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .formatted(formatter)
do {
    let decoded = try decoder.decode(Exercise.self, from: json)
    print(decoded.id)
} catch {
    print(error.localizedDescription)
}

4      

Many thanks for that. I looked at keycodingstatergy but seemed hard.

https://developer.apple.com/documentation/foundation/jsondecoder/keydecodingstrategy

2      

Another quick question, hpw do you handle nestd data in the JSON eg.

let json = """
{
"id": 1937529874,
"upload-time": "2008-10-13",
"polar-user": "Matthew"
"heart-rate": {
    "average": 120
    "maximum": 160
}
""".data(using: .utf8)!

struct Heart: Codable {
    var average: Int
    var maximum: Int
}

struct Exercise: Codable {
    var id: Int
    var uploadTime: Date?
    var polarUser: String
    var heart: Heart

    enum CodingKeys: String, CodingKey {
        case id
        case uploadTime = "upload-time"
        case polarUser = "polar-user"
        case heart
        ?????
    }
}

2      

import UIKit

let json = """
{
"id": 1937529874,
"upload-time": "2008-10-13",
"polar-user": "Matthew",
"heart-rate": {
    "average": 120,
    "maximum": 160
    }
}
""".data(using: .utf8)!

struct HeartRate: Codable {
    var average: Int
    var maximum: Int

// CodingKeys isn't strictly necessary here
//   but I like to include it anyway because
//   I prefer things to be explicit.
//   You can do whichever you prefer

//    enum CodingKeys: String, CodingKey {
//        case average
//        case maximum
//    }
}

struct Exercise: Codable, Identifiable {
    var id: Int
    var uploadTime: Date?
    var polarUser: String
    var heartRate: HeartRate

    enum CodingKeys: String, CodingKey {
        case id
        case uploadTime = "upload-time"
        case polarUser = "polar-user"
        case heartRate = "heart-rate"
    }
}

let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd"

let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .formatted(formatter)
do {
    let decoded = try decoder.decode(Exercise.self, from: json)
    print(decoded)
} catch {
    print(error.localizedDescription)
}

2      

You could also nest the HeartRate struct inside the Exercise struct, like so:

struct Exercise: Codable, Identifiable {
    var id: Int
    var uploadTime: Date?
    var polarUser: String
    var heartRate: HeartRate

    struct HeartRate: Codable {
        var average: Int
        var maximum: Int
    }

    enum CodingKeys: String, CodingKey {
        case id
        case uploadTime = "upload-time"
        case polarUser = "polar-user"
        case heartRate = "heart-rate"
    }
}

2      

Thank you very much.

2      

Quinn, I'm still finding my way through some of these concepts, but I noticed that you said CodingKeys seemed hard. Of course; they're not familiar looking things. But I'll call on former teaching experience and encourage you to watch a variety of YouTubes, then Paul's HWS videos again. Take breaks between each view, and give yourself another 5 or 6 exposures; by the fifth view, things will seem more familiar.

2      

Hacking with Swift is sponsored by Essential Developer

SPONSORED Join a FREE crash course for mid/senior iOS devs who want to achieve an expert level of technical and practical skills – it’s the fast track to being a complete senior developer! Hurry up because it'll be available only until April 28th.

Click to save your free spot now

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.