-1

I'm making an api call to get some data, the json dataAsString looks like this...

   guard let dataAsString = String(data: data, encoding: .utf8)else {return}
     print(dataAsString)

JSON DATA

{"patch_report":{"name":"macOS Updates","patch_software_title_id":"1","total_computers":"5","total_versions":"1","versions":{"version":{"software_version":"10.15.3","computers":{"size":"5","computer":{"id":"467","name":"EPART1BGF8J9"}}}}}}
     do {
            // make sure this JSON is in the format we expect
            if let json = try JSONSerialization.jsonObject(with:data, options:[]) as? [String: Any] {
                // try to read out a string array
                if let patch_report = json["patch_report"] as? [String] {
                    print(patch_report)
                }
            }
        } catch let error as NSError {
            print("Failed to load: \(error.localizedDescription)")
        }

How could I use JSONSerialization to get only certain nested JSON values? I've been told by many not to use JSONSerialization so I've provided an alternate solution. Below has the Codable solution as well. Click Here For An Explination - Using Codable with nested JSON!

I was able to find the answers below...

Get nested JSON using JSONSerialization

        do {
            // make sure this JSON is in the format we expect
            if let json = try JSONSerialization.jsonObject(with:data, options:[]) as? [String: Any] {
                // try to read out a string array
                if let patch_report = json["patch_report"] as? [String:Any] {
                    if let versions = patch_report["versions"] as? [String:Any] {
                        if let version = versions["version"] as? [String:Any] {
                            if let software_version = version["software_version"] as? String {
                                print(software_version)
                            }
                        }}

                }    else {print("Not Available")}
            }
        } catch let error as NSError {
            print("Failed to load: \(error.localizedDescription)")
        }

Get nested Json using Decoder

  struct PatchReport: Codable {

        var patch_report:Patch_report?

        enum CodingKeys: String, CodingKey{
            case patch_report = "patch_report"
        }

        struct Patch_report: Codable {

        var name:String?
        var patch_software_title_id:String?
        var total_computers:String?
        var total_versions:String?
        var versions: Versions?

        enum CodingKeys: String, CodingKey {
            case name = "name"
            case patch_software_title_id = "patch_software_title_id"
            case total_computers = "total_computers"
            case total_versions = "total_versions"
            case versions = "versions"
        }

        struct Versions: Codable {
            var version: Version?

            enum CodingKeys: String, CodingKey {
                case version = "version"
            }


        struct Version: Codable {
            var software_version:String?
            var computers:Computers?

            enum CodingKeys: String, CodingKey {
                case software_version = "software_version"
                case computers = "computers"
            }

            struct Computers: Codable{
                      var size:String?
                      var computer:Computer?

                enum CodingKeys: String, CodingKey {
                    case size = "size"
                    case computer = "computer"
                }

                struct Computer: Codable{
                    var id:String?
                    var name:String?

                    enum CodingKeys: String, CodingKey {
                        case id = "id"
                        case name = "name"
                            }
                        }
                  }
            }
        }
    }
}
let response = try! JSONDecoder().decode(PatchReport.self, from: data)
print(String(response.patch_report?.total_computers ?? ""))
Mdoyle1
  • 121
  • 1
  • 12
  • 2
    Abandon JSONSerialization. Use Codable instead. Anyway `json["patch_report"]` is not a `[String]`. It’s a dictionary. – matt Feb 26 '20 at 15:27
  • What would the Codable struct look like? – Mdoyle1 Feb 26 '20 at 15:33
  • 1
    `if let patch_report = json["patch_report"] as? [String] { A() } else { B() }`, it's important that you know what can make it go to B() and what to A(). If `json["patch_report"]` is nil, go to B(). If `json["patch_report"]` is not a `[String]` (array of String), it will go to B(). Which reason do you think it is for you? That's important step in debugging and autonomy. – Larme Feb 26 '20 at 15:38

1 Answers1

1

You're trying to cast patch_report as a String which won't work. Try this instead:

if let patch_report = json["patch_report"] as? [String: Any] {
    print(patch_report["name"])
}
rodskagg
  • 3,827
  • 4
  • 27
  • 46