3

The JSON from server looks like this:

A dictionary where the value is another dictionary.

{
    "S1": {
        "vpn_status": 2,
        "vpn_name": "vpn1"
    },
    "S2": {
        "vpn_status": 1,
        "vpn_name": "vpn2"
    }
}

I have created the following struct to parse it.

public struct ServerStatusResult {

    public let vpnName: String
    public let status: Int

    init?(json: [String: Any]) {
        guard
            let vpnName = json["vpn_name"] as? String,
            let status = json["vpn_status"] as? Int
            else {
                return nil
        }
        self.vpnName = vpnName
        self.status = status
    }
}

And the function to call the server is:

typealias serverStatusCompletedClosure = (_ status: Bool, _ result: Dictionary<String,ServerStatusResult>?, _ error: ServiceError?)->Void

func serverStatus(email: String, password: String, complete: @escaping serverStatusCompletedClosure) {
        let url = URL(string: "...")!
        try? self.httpClient.get(url: url,
                                token: "...",
                                email: email,
                                password: password)
        { (data, response, error) in
            if let error = error {
                complete(false, nil, ServiceError.invalidSession)
            } else if let httpResponse = response as? HTTPURLResponse {
                switch (httpResponse.statusCode) {
                case 200:
                    var result: [String:ServerStatusResult]? = nil
                    result = try! JSONSerialization.jsonObject(with: data!, options: []) as! Dictionary<String, ServerStatusResult>
                    complete(true, result, nil)

This is where my json transformation fails.

Could not cast value of type '__NSDictionaryI' (0x7fff8eaee9b0) to 'app.ServerStatusResult' (0x10021dec0).

What am I missing please?

6
  • 1
    Why not use Decodable and decode a dictionary [String: ServerStatusResult]? ` Commented Apr 3, 2020 at 8:22
  • Sure, can you show me how? :-) Commented Apr 3, 2020 at 8:23
  • Try using JSONDecoder instead of JSONSerialization Commented Apr 3, 2020 at 8:23
  • Are you sure the response? Because the response which you shared is not has a type like [String: ServerStatusResult] if it is you missed something because I couldn't see any [ ] between String to ServerStatusResult fields Commented Apr 3, 2020 at 8:26
  • is there a fix number of dict inside the main dictionary or it can be any? Commented Apr 3, 2020 at 8:26

2 Answers 2

1

You can solve it by using Decodable and using a dictionary

First make your struct conform to Decodable

public struct ServerStatusResult: Decodable {
    public let vpnName: String
    public let status: Int

    enum CodingKeys: String, CodingKey {
        case vpnName = "vpn_name"
        case status = "vpn_status"
    }
}

and then the decoding is easy

do {
    let result = try JSONDecoder().decode([String: ServerStatusResult].self, from: data)
    print(result) //or in you case complete(true, result, nil)
} catch {
    print(error)
}
Sign up to request clarification or add additional context in comments.

Comments

0

You get an array of dictionary [[String: Any]]

Create a struct for a dictionary and if a dictionary has another dictionary inside it then create another struct for the inner Dictionary and create an object in the outer struct for innner dictionary json.

You can use codeable to parse your json easily, by inheriting your struct with codeable

Comments

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.