NEW: Learn to build amazing SwiftUI apps for macOS with my new book! >>

How to handle different JSON from the same URL request

Forums > Swift

Hi guys,for the same URL request I can have a different json response from the API. For success I've something like this:

{
    "error": "false",
    "value": {
        "person": {
            "personId": 1529853,
            "name": "test",
            "firstName": "tezt",
            "civility": "MR",
            "fidelityCode": "LM57CC",
            "phoneCode": "+237",
            "phoneNumber": "+237",
            "cniCode": null,
            "email": "test6@adwa.cm",
            "vipStatus": 0,
            "activationStatus": 1,
            "countryCode": 30,
            "birthDate": "2002-10-12",
            "searchStatus": "RAS"
        }
    }
}

For error I've something like this:

{
    "error": "false",
    "value": {
        "person": -1
    }
}

How can I handle it to know when it's a success or error?

1      

Basically, you need to use an enum for the "person" key with two cases have associated values of either an Int or a Person. Here is a SwiftUI view that I whipped up to demonstrate:

import SwiftUI

struct Person: Decodable {
    let personId: Int
    let name: String
    let firstName: String
    let civility: String
    let fidelityCode: String
    let phoneCode: String
    let phoneNumber: String
    let cniCode: String?
    let email: String
    let vipStatus: Int
    let activationStatus: Int
    let countryCode: Int
    let birthDate: String
    let searchStatus: String
}

enum PersonOrError: Decodable {
    case personVal(Person)
    case errorVal(Int)

    init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        if let intVal = try? container.decode(Int.self) {
            self = .errorVal(intVal)
            return
        }
        if let personVal = try? container.decode(Person.self) {
            self = .personVal(personVal)
            return
        }
        throw DecodingError.typeMismatch(PersonOrError.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for ValueUnion"))
    }
}

struct Value: Decodable {
    let person: PersonOrError
}

struct PEResponse: Decodable {
    let error: String
    let value: Value
}

struct PersonOrErrorView: View {

    let jsonError = {
        return """
{
    "error": "false",
    "value": {
        "person": -1
    }
}
""".data(using: .utf8)!
    }()

    let jsonPerson = {
      return """
{
    "error": "false",
    "value": {
        "person": {
            "personId": 1529853,
            "name": "test",
            "firstName": "tezt",
            "civility": "MR",
            "fidelityCode": "LM57CC",
            "phoneCode": "+237",
            "phoneNumber": "+237",
            "cniCode": null,
            "email": "test6@adwa.cm",
            "vipStatus": 0,
            "activationStatus": 1,
            "countryCode": 30,
            "birthDate": "2002-10-12",
            "searchStatus": "RAS"
        }
    }
}
""".data(using: .utf8)!
    }()

    enum PorE {
        case person, error
    }
    @State private var whichJSON: PorE = .person

    @State private var textDisplay: String = ""

    var body: some View {
        VStack {
            Text(textDisplay)
            Button("Switch") {
                whichJSON = whichJSON == .person ? .error : .person
            }
        }
        .onAppear { loadJSON() }
        .onChange(of: whichJSON) { _ in
            loadJSON()
        }
    }

    func loadJSON() {
        let decoder = JSONDecoder()
        do {
            let response =
                try decoder.decode(PEResponse.self,
                                   from: whichJSON == .person ? jsonPerson : jsonError)
            switch response.value.person {
            case .errorVal(let i): textDisplay = "Error \(i)"
            case .personVal(let p): textDisplay = p.name
            }
        }
        catch {
            textDisplay = "Error!"
        }
    }
}

struct PersonOrErrorView_Previews: PreviewProvider {
    static var previews: some View {
        PersonOrErrorView()
    }
}

Hopefully this makes sense.

1      

I totally forgot after testing, thank you so much 🙏

1      

Hacking with Swift is sponsored by RevenueCat

SPONSORED Spend less time managing in-app purchase infrastructure so you can focus on building your app. RevenueCat gives everything you need to easily implement, manage, and analyze in-app purchases and subscriptions without managing servers or writing backend code.

Get Started

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.