1

I have a struct that I describe in a JSON file, say the struct is named Dog

struct Dog {
  var color: UIColor
}

I'm keeping track of my dogs in a dictionary in a JSON file where each dog's name act as an identifier. So I could have the next JSON:

"myDogs": {

  "goodBoy": {
    "color": "#000000"
  },

  "veryGoodBoy": {
    "color": "#FFFFFF
  }

}

To descrive my 2 dogs, it being a dictionary I (obviously) want to avoid duplicate keys, so I would expect that when I decode myDogs that is of type [String: Dog] if the JSON has 2 dogs with the same key (name) I would get some error.

To my surprise it's not happening, instead it just ignores all the dogs after the first one, i.e for this JSON

"myDogs": {

  "goodBoy": {
    "color": "#000000"
  },

  "veryGoodBoy": {
    "color": "#FFFFFF
  }

  "goodBoy": {
    "color": "#FF0000"
  }

}

I would get a dictionary with 2 dogs, one name "goodBoy" with black color, and another named "veryGoodBoy" with white color.

Is there a way to raise an exception (or at least log an error) in the decoding stage?

Thanks in advance.

Edit

Does JSON syntax allow duplicate keys in an object? helps but it doesnt answer my question. Basically I'm asking is there a way in Swift to raise an exception in the decoding stage without rewriting JSONDecoder()

Luca Angeletti
  • 58,465
  • 13
  • 121
  • 148
  • a key shouldn't be repeated in your response – Shehata Gamal Dec 31 '19 at 13:55
  • Does this answer your question? [Does JSON syntax allow duplicate keys in an object?](https://stackoverflow.com/questions/21832701/does-json-syntax-allow-duplicate-keys-in-an-object) – Gereon Dec 31 '19 at 13:56
  • The three-key JSON is not even valid. `JSONDecoder()` decodes two keys and ignores the duplicate. But actually it's the business of the server to avoid duplicate keys in a dictionary. – vadian Dec 31 '19 at 14:02
  • @Gereon thank you, this helped my understanding of JSON conventions. But it does not answer my question, is there a way in Swift to raise an exception in the decoding stage without rewriting `JSONDecoder()`? –  Dec 31 '19 at 14:09
  • I don't think there is, and I also don't think you can expect there to be one if the JSON in question is not obviously malformed, according to the standard. – Gereon Dec 31 '19 at 15:47

1 Answers1

0

Ok so you want to know if there is a way of detecting the duplicate key error with JSONDecoder.

Honestly I didn't know the answer so I investigated a bit.

1. Let's fix your JSON keeping the duplicate key inconsistency

Your input JSON has several errors besides the duplicate key.

  1. A JSON should being with { or ] and ending with the same symbol as well
  2. There is a missing " at the end of "#FFFFFF
  3. There is a missing , at the end of
  "veryGoodBoy": {
    "color": "#FFFFFF
  }

Let's apply these fixes and we finally get a JSON where the only error is the duplicate key

let data = """
{
    "myDogs": {

      "goodBoy": {
        "color": "#000000"
      },

      "veryGoodBoy": {
        "color": "#FFFFFF"
      },

      "goodBoy": {
        "color": "#FF0000"
      }
    }
}
""".data(using: .utf8)!

2. The Codable struct

Now we can define a Codable type (I usually prefer a struct when decoding JSONs) to match the input JSON

struct Response: Decodable {

    let myDogs: [String: Dog]

    struct Dog: Decodable {
        let color: String
    }
}

3. Decoding

Finally let's try decoding the JSON

do {
    let dict = try JSONDecoder().decode(Response.self, from: data)
    print(dict)
} catch {
    print(error)
}

This code runs fine without raising an error. But (of course) the resulting value has a missing entry

Why did I say "of course"? Because Swift dictionaries cannot have duplicated keys.

Response(
    myDogs: [
        "goodBoy": Dog(color: "#000000"),
        "veryGoodBoy": Dog(color: "#FFFFFF")
    ]
)

4. Considerations

So as far as I can see, the answer to your question is: NO, we cannot detect a duplicate key in the original JSON with JSONDecoder.

Luca Angeletti
  • 58,465
  • 13
  • 121
  • 148