New to YAML: not parsing in Swift

88 Views Asked by At

Here's some yaml that I've generated :

byTeam:
    - t0: { description: "Find a video of an object being selected and deselected", bestAnswer: [ 0 ]}
    - t1: { description: "Reveal and hide numeric controls", bestAnswer: [ 1 ]}
    - t2: { description: "Reveal and hide the tools", bestAnswer: [ 2 ]}

the error I get when parsing this is:

no decode typeMismatch(Yams.Node.Mapping, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "assignments", intValue: nil), _YAMLCodingKey(stringValue: "Index 1", intValue: 1), CodingKeys(stringValue: "challenges", intValue: nil), _YAMLCodingKey(stringValue: "Index 0", intValue: 0), CodingKeys(stringValue: "byTeam", intValue: nil)], debugDescription: "Expected to decode Mapping but found Node instead.", underlyingError: nil))

This is new data, nested further into an already working yaml file. It's intended to end up parsed into this structure:

    struct CodableChallenge : Codable {
        var title :                     String
        var type :                      String
        var description :               String
        var uuid :                      UUID
        var videos :                    Array<String>
        var bestAnswer :                Array<Int>
        var userAnswer :                Array<Int>?
        var byTeam :                    Dictionary<String, TeamChallenge>?
    }
    
    struct TeamChallenge : Codable {
        var description :               String
        var bestAnswer :                Array<Int>
    }

The code generating the error is

 do {
            let decoded = try decoder.decode(MenuScreenVC.CodableCurriculum.self, from: src)
            manifestObsolete = curriculum == nil || decoded.referenceDate! > curriculum!.referenceDate!
            self.newManifest = decoded
            NotificationCenter.default.post(name: NSNotification.Name("gotManifest"), object: nil)
            return
        } catch {
            print("no decode \(error)")
        }

I am not completely unfamiliar with yaml, I used it a lot years ago with RoR. But I think what's escaping me is the deeper nesting. The error seems to indicate that it's getting data that doesn't look like straightforward mapping, but why?

1

There are 1 best solutions below

9
Alexander On

You're mixing arrays and dictionaries in a way that doesn't really make sense, and which doesn't match what your code expects.

Each tick mark starts a new object. Each colon-suffixed label demarks a key in an object. So what you've written is in effect:

byTeam: [
    { t0: { ... } },
    { t1: { ... } },
    { t2: { ... } },
]

You just need to get rid of these tN values:

byTeam:
    - { description: "Find a video of an object being selected and deselected", bestAnswer: [ 0 ]}
    - { description: "Reveal and hide numeric controls", bestAnswer: [ 1 ]}
    - { description: "Reveal and hide the tools", bestAnswer: [ 2 ]}

Although using the JSON-style object syntax ({}) might not be warranted in this case. I think it's more clear to use the normal YAML syntax:

byTeam:
  - description: "Find a video of an object being selected and deselected"
    bestAnswer: [0]

  - description: "Reveal and hide numeric controls"
    bestAnswer: [1]

  - description: "Reveal and hide the tools"
    bestAnswer: [2]

(Adding spacing lines between the array items isn't necessary by the YAML grammar, but can help readability in some cases. Play with it to see what's best, especially if it might help your non-technical audience to better understand these.)