20

I have been working with the Codable protocol

Here is my JSON file :

    {  
   "Adress":[  

   ],
   "Object":[  
      {  
         "next-date":"2017-10-30T11:00:00Z",
         "text-sample":"Some text",
         "image-path":[  
            "photo1.png",
            "photo2.png"
         ],
         "email":"john.doe@test.com",
         "id":"27"
      },
      {  
         "next-date":"2017-10-30T09:00:00Z",
         "text-sample":"Test Test",
         "image-path":[  
            "image1.png"
         ],
         "email":"name.lastename@doe.com",
         "id":"28"
      }
   ]
}

I only have to focus on the Object array, and the "image-path" array can contain 0, 1, or 2 strings.

So here is my implementation:

struct Result: Codable {
    let Object: [MyObject]
}

struct MyObject: Codable {

    let date: String
    let text: String
    let image: [String]
    let email: String
    let id: String

    enum CodingKeys: String, CodingKey {
        case date = "next-date"
        case text = "text-sample"
        case image = "image-path"
        case email = "email"
        case id = "id"
    }

    init() {
        self.date = ""
        self.text = ""
        self.image = []
        self.email = ""
        self.id = ""
    }
}

I call it from my service class after requesting and getting the JSON data this way:

if let data = response.data {
                let decoder = JSONDecoder()
                let result = try! decoder.decode(Result, from: data)
                dump(result.Object)
            }

Everything is working except the [String] for the image property

But it can't compile, or I get an "Expected to decode..." error.

How should I handle the nil/no data scenario?

  • 3
    Basically the code (the first implementation) is supposed to work, but the JSON is not valid. You don't need the `init` method at all if you are always using the decoder. – vadian Oct 30 '17 at 11:21

1 Answers1

8

I have made a small change in your MyObject struct, i.e.,

1. Marked all properties as optionals

2. Removed init() (I don't think there is any requirement of init() here.)

3. Use Result.self instead of Result in decoder.decode(...) method

struct MyObject: Codable
{
    let date: String?
    let text: String?
    let image: [String]?
    let email: String?
    let id: String?

    enum CodingKeys: String, CodingKey
    {
        case date = "next-date"
        case text = "text-sample"
        case image = "image-path"
        case email = "email"
        case id = "id"
    }
}

To test the above, I have used the below code and it is working fine.

    let jsonString = """
        {"Adress": [],
        "Object": [{"next-date": "2017-10-30T11:00:00Z",
        "text-sample": "Some text",
        "image-path": ["photo1.png", "photo2.png"],
        "email": "john.doe@test.com",
        "id": "27"},
      {"next-date": "2017-10-30T09:00:00Z",
       "text-sample": "Test Test",
       "image-path": ["image1.png"],
       "email": "name.lastename@doe.com",
       "id": "28"}
       ]
        }
    """
    if let data = jsonString.data(using: .utf8)
    {
        let decoder = JSONDecoder()
        let result = try? decoder.decode(Result.self, from: data) //Use Result.self here
        print(result)
    }

This is the result value that I am getting:

enter image description here

PGDev
  • 23,751
  • 6
  • 34
  • 88
  • With same sample I can't make it work. "debugDescription: "Expected to decode Array but found a string/data instead.", underlyingError: nil)): file /Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-900.0.65.2/src/swift/stdlib/public/core/ErrorType.swift, line 181" –  Oct 30 '17 at 12:38
  • Did you use Result.self? – PGDev Oct 30 '17 at 12:39
  • Nevermind. Never trust backend, I had a typo in the json from production. My code was working since the beginning... Thank you anyway :) –  Oct 30 '17 at 12:49
  • Sure..Happy coding..:) – PGDev Oct 30 '17 at 12:50
  • 6
    ```Marked all properties as optionals``` — why would you do that? – user28434'mstep Oct 30 '17 at 13:13
  • 4
    Because it is not confirmed that you will get all the key-value pairs from API. Instead of initialising them with empty string/array, its better they are nil. That is the reason I used optional for them. – PGDev Oct 30 '17 at 13:15
  • 10
    @PGDev absolutely correct. Never trust a backend :-) – brainray Mar 18 '18 at 15:47