-1

I have json data with the same core structure from a nosql database (PK, SK, attributes). The attributes part will be different depending on the value of SK.

Example:

[
  {
    "PK": "POLL#1544693DF0E88EC-3225-410E-B156-D13781B238F6",
    "SK": "#METADATA#1544693DF0E88EC-3225-410E-B156-D13781B238F6",
    "attributes": {
      "latitude": "53.34589121858683",
      "longitude": "-6.272215191675388",
      "max_choices": 50,
      "number": "1544693",
      "poll_open": false,
    }
  },
  {
    "PK": "POLL#1544693DF0E88EC-3225-410E-B156-D13781B238F6",
    "SK": "CHOICE#00a6ec5c-acc1-40f1-a087-31160d2cfc65",
    "attributes": {
      "distance": 790.95097525,
      "latitude": 53.3416,
      "price": "€€",
      "categories": [
        {
          "title": "Ramen",
          "alias": "ramen"
        }
      ],
      "vote_count": 0,
      "longitude": -6.26274
    }
  }
]

Is it possible to use decode without errors? I've been stuck on this for hours.

I've defined the following:

struct Result: Codable {
    var PK: String
    var SK: String
    var attributes: String
}

But, when I decode, I get the error:

typeMismatch(Swift.String, Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "Index 0", intValue: 0), CodingKeys(stringValue: "attributes", intValue: nil)], debugDescription: "Expected to decode String but found a dictionary instead.", underlyingError: nil))

I just want to decode 'attributes' as a generic string and parse it later depending on the value of SK when I know how to properly handle it. Why is this so difficult?

mrshanes
  • 9
  • 2
  • 2
    It is exactly what the error says, `attribute` is not a string but a dictionary (or a custom type) so you need to create a separate struct for `attributes` – Joakim Danielson Nov 03 '20 at 21:20
  • I understand that, but I won't always know the structure of attributes when first getting it. That's the reason I want to load it as a generic string here and parse it later when interating through the content. – mrshanes Nov 06 '20 at 18:13
  • There is no such thing as a generic string, you could handle it as a dictionary. – Joakim Danielson Nov 06 '20 at 18:15
  • 'attributes' could have 3 or 4 different formats. How would I define that using Codable? It appears that I can't. – mrshanes Nov 06 '20 at 20:34

2 Answers2

0

Do you need attributes right now? Or are you just looking for pk and sk? If you do not need it just do not include

var attributes: String

in your struct. It will not have a decode error and it will decode the other two, you just will not get the attributes parameter. It is not able to decode the attributes as a string because it is not. It is really more like a dictionary. Swift does not know how to handle that unless you specifically tell it. That being said you could always do this

struct Result: Codable {
var PK: String
var SK: String
var attributes: Attributes
}

struct Attributes: Codable {
var lattitude: String
var longitude: String
//and whatever else you know you have
}

the key is only adding the values you know will be included in the attributes or else it will give an error

Jwoodland
  • 16
  • 4
0

You need to handle this using JSONSerialization instead of Codable. Given you still want to use the same struct you need to change it to

struct Result {
    var PK: String
    var SK: String
    var attributes: [String: Any]
}

and decode the json like this

var result: Result?
do {
    if let dictionary = try JSONSerialization.jsonObject(with: data) as? [String: Any],
       let pk = dictionary["PK"] as? String,
       let sk = dictionary["SK"] as? String,
       let attributes = dictionary["attributes"] as? [String: Any] {
        result = Result(PK: pk, SK: sk, attributes: attributes)
    }
} catch {
    print(error)
}

Now you still need to convert the attributes ([String: Any]) property of Result to something more usable but that is beyond this question

Joakim Danielson
  • 43,251
  • 5
  • 22
  • 52