2

I'm trying to parse some data from JSON, I already got that working with another API but now I have another struct and I'm getting typeMissmatch Erros...

The JSON looks like:

{
"status": 200,
"data": {
"date": "2018-04-07T00:00:00.508Z",
"featured": [
  {
    "id": "2345",
    "name": "name",
    "price": "1,000",
    "priceIcon": "String",
    "priceIconLink": "URLString",
    "images": {
      "icon": "URLString",
      "png": "URLString",
      "gallery": "URLString",
      "featured": "URLString"
    },
    "rarity": "1String",
    "type": "1String",
    "readableType": "1String"
  }
],
"daily": [
        {
            "id": "12324",
            "name": "name",
            "price": "1,500",
            "priceIcon": "String",
            "priceIconLink": "URLString",
            "images": {
                "icon": "URLString",
                "png": "URLString",
                "gallery": "URLString",
                "featured": "URLString"
            },
            "rarity": "1String",
            "type": "1String",
            "readableType": "1String"
        }
    ]
}}

And a Codable struct like that:

    struct Base : Codable {
    let status : Int
    let data : DataItems
   }

struct DataItems : Codable {
    let date : String
    let featured : [Featured]
    let daily : [Daily]
}

struct Featured : Codable {
    let id : String
    let name : String
    let price : String
    let priceIcon : String
    let priceIconLink : String
    let images : Images
    let rarity : String
    let type : String
    let readableType : String
}

struct Daily : Codable {
    let id : String
    let name : String
    let price : String
    let priceIcon : String
    let priceIconLink : String
    let images : Images
    let rarity : String
    let type : String
    let readableType : String
}

struct Images : Codable {
    let icon : String
    let png : String
    let gallery : String
    let featured : String

}

But when I try to decode that Json I get a "Swift.DecodingError.typeMismatch" Error:

    ▿ Swift.DecodingError.typeMismatch
  ▿ typeMismatch: (2 elements)
    - .0: Swift.String #0
    ▿ .1: Swift.DecodingError.Context
      ▿ codingPath: 5 elements
        - CodingKeys(stringValue: "data", intValue: nil)
        - CodingKeys(stringValue: "daily", intValue: nil)
        ▿ _JSONKey(stringValue: "Index 0", intValue: 0)
          - stringValue: "Index 0"
          ▿ intValue: Optional(0)
            - some: 0
        - CodingKeys(stringValue: "images", intValue: nil)
        - CodingKeys(stringValue: "featured", intValue: nil)
      - debugDescription: "Expected to decode String but found a number instead."
      - underlyingError: nil

My JSON Decoder:

 enum Result<Value> {
    case success(Value)
    case failure(Error)
}

func getItems(for userId: Int, completion: ((Result<Base>) -> Void)?) {
    var urlComponents = URLComponents()
    urlComponents.scheme = "https"
    urlComponents.host = "api.jsonbin.io"
    urlComponents.path = "/myurl"
    let userIdItem = URLQueryItem(name: "userId", value: "\(userId)")
    urlComponents.queryItems = [userIdItem]
    guard let url = urlComponents.url else { fatalError("Could not create URL from components") }

    var request = URLRequest(url: url)
    request.httpMethod = "GET"


    let config = URLSessionConfiguration.default
    config.httpAdditionalHeaders = [
        "secret-key": "xyz"
    ]

    let session = URLSession(configuration: config)
    let task = session.dataTask(with: request) { (responseData, response, responseError) in
        DispatchQueue.main.async {
            if let error = responseError {
                completion?(.failure(error))
            } else if let jsonDataTest = responseData {
                // Now we have jsonData, Data representation of the JSON returned to us
                // from our URLRequest...

                // Create an instance of JSONDecoder to decode the JSON data to our
                // Codable struct
                let decoder = JSONDecoder()

                do {
                    // We would use Post.self for JSON representing a single Post
                    // object, and [Post].self for JSON representing an array of
                    // Post objects
                    let posts = try decoder.decode(Base.self, from: jsonDataTest)
                    completion?(.success(posts))
                } catch {
                    completion?(.failure(error))
                }
            } else {
                let error = NSError(domain: "", code: 0, userInfo: [NSLocalizedDescriptionKey : "Data was not retrieved from request"]) as Error
                completion?(.failure(error))
            }
        }
    }

    task.resume()
}

var base:Base?

func loadJson() {
    getItems(for: 1) { (result) in
        switch result {
        case .success(let base):
            self.base = base
            dump(base)
        case .failure(let error):
          fatalError("error: \(error.localizedDescription)")
        }
    }
}

I'm new to swift and not sure what this Error is telling me or where the problem "decode String but found a number" is. I think there is something wrong with me struct.. I hope someone can help me there.

1 Answer 1

3

Please show the code where you want to parse the data to json.

    let urlString = "your_url.json"
    guard let url = URL(string: urlString) else { return }

    URLSession.shared.dataTask(with: url) { (data, response, error) in
        if error != nil {
            print(error!.localizedDescription)
        }

        guard let data = data else { return }

            do {
            //Decode retrived data with JSONDecoder and assing type of Article object
            let baseData = try JSONDecoder().decode(Base.self, from: data)
            print(baseData) //whole project
            print(baseData.status) //200.0
            print(baseData.data.date)
            for day in baseData.data.daily {
                print(day.id)
                print(day.images.icon)
                print(day.images.featured)
                print(day.images.gallery)
                print(day.images.png)
                print(day.name)
                print(day.price)
                print(day.priceIcon)
                print(day.priceIconLink)
                print(day.rarity)
                print(day.readableType)
                print(day.type)
            }

            for feature in baseData.data.featured {
                print(feature.id)
                print(feature.images.icon)
                print(feature.images.featured)
                print(feature.images.gallery)
                print(feature.images.png)
                print(feature.name)
                print(feature.price)
                print(feature.priceIcon)
                print(feature.priceIconLink)
                print(feature.rarity)
                print(feature.readableType)
                print(feature.type)
            }
        } catch let jsonError {
            print(jsonError)
        }
        }.resume()

I tried this and it works for me.

By the way I was a little bit confused that Featured and Daily have all the same variables but are different models.

EDIT

Your posted data in the question are valid. The json from https://api.jsonbin.io/b/5acbd2dc214f9a2b84c6f167/1 is wrong or not consistent.

There is "featured": false in Daily and in Featured it is a string. In the struct is a string expected. So you will get a mismatch. Once you try to parse a string (works) and then you try to parse a boolean to a string (error).

Sign up to request clarification or add additional context in comments.

4 Comments

api.jsonbin.io/b/5acbd2dc214f9a2b84c6f167/1 This is the JSON I'm trying to get. And added decoder to my question
yeah I understand. My code exactly do this. add https://api.jsonbin.io/b/5acbd2dc214f9a2b84c6f167/1 to your_url.json and you will get all your datas.
See my EDIT. Your json data different.
I realized that I don't need the featured section. I don't parse it and its ok... Thanks for your help, you helped me a lot!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.