简体   繁体   中英

How to parse this JSON and create struct for

I have a JSON:

[
{
  "Men": {
    "image": "/url.png",
    "Jeans": [
      {
        "name": "asd",
        "about": "sadvc",
        "image": "/urls.sjd"
      },
      {
        "name": "asd",
        "about": "sadvc",
        "image": "/urls.sjd"
      },
      {
        "name": "asd",
        "about": "sadvc",
        "image": "/urls.sjd"
      }
    ]
  },
  "Women": {
    "image": "/url2.jpeg",
    "All": {}
  }
}
]

How to create the struct for "step by step" going into the tableview?

First View - Change sex - Women or men. Second - Change type - jeans or other... Thirst - collection view with jeans (name, about and price).

Now, i have struct

struct Clothe: Decodable {
    let about: String
    let name: String
    let image: String
}

And func for downloading JSON

var clothes = [Clothe]()
public func downloadJSON(completed: @escaping () -> ()) {
    let url = URL(string: "https...bla-bla/ULRhere.json")

    let request = URLRequest(url: url!, cachePolicy: .reloadIgnoringLocalAndRemoteCacheData, timeoutInterval: 120.0)

    URLSession.shared.dataTask(with: request) { (data, response, error) in
        if error == nil {
            do {
                self.clothes = try JSONDecoder().decode([Clothe].self, from: data!)
                print(self.clothes)
                DispatchQueue.main.async {

                    completed()

                }
            } catch {
                print("JSON Error")
            }
        }

        }.resume()
}

在此处输入图片说明 let json = """{"Men": {"image": "/url.png","Jeans": [{"name": "asd","about": "sadvc","image": "/urls.sjd"},{"name": "asd","about": "sadvc","image": "/urls.sjd"},{"name": "asd","about": "sadvc","image": "/urls.sjd"}]},"Women": {"image": "/url2.jpeg","All": {}}}""".data(using: .utf8)!

struct Cloth: Decodable {
let Men : MenStruct?
let Women : WomanStruct?}

struct MenStruct: Decodable {
let image: String?
let Jeans: [JeansStruct]?}

struct JeansStruct: Decodable {
let name: String?
let about: String?
let image: String?}

struct WomanStruct: Decodable {
let image: String?}

func executeJson(){
do {
    let cloth = try JSONDecoder().decode(Cloth.self, from: json)
    print(cloth)
}catch {
    print("JSON Error")
}}

executeJson()

Cloth(Men: Optional(__lldb_expr_88.MenStruct(image: Optional("/url.png"), Jeans: Optional([__lldb_expr_88.JeansStruct(name: Optional("asd"), about: Optional("sadvc"), image: Optional("/urls.sjd")), __lldb_expr_88.JeansStruct(name: Optional("asd"), about: Optional("sadvc"), image: Optional("/urls.sjd")), __lldb_expr_88.JeansStruct(name: Optional("asd"), about: Optional("sadvc"), image: Optional("/urls.sjd"))]))), Women: Optional(__lldb_expr_88.WomanStruct(image: Optional("/url2.jpeg"))))

This is not a good JSON design. I would suggest not using data values ("Men" and "Women" or "Jeans" vs another type of clothing) as keys to your dictionary.

Also, I'd suggest that the response from your web service return a dictionary with keys like a success value (a Boolean that indicates whether the result was successful or not) and a result key (for the contents of the response). This way, if there is an error, the basic structure of the response will be the same (but a successful response will include result key and a failure might include an error message or error code).

Anyway, I'd suggest something like:

{
    "success": true,
    "result": [{
        "name": "Men",
        "image": "men.png",
        "productLine": [{
            "name": "Jeans",
            "image": "jeans.png",
            "products": [{
                    "name": "Slim fit",
                    "about": "Slim Fit Jeans",
                    "image": "slim.png"
                },
                {
                    "name": "Bell Bottom",
                    "about": "Cool bell bottom jeans",
                    "image": "bellbottom.png"
                },
                {
                    "name": "Acid Wash",
                    "about": "Acid wash jeans",
                    "image": "acid.png"
                }
            ]
        }]
    }, {
        "name": "Women",
        "image": "women.jpeg"
    }]
}

Then you can set up logical model entities:

struct Product: Codable {
    let about: String
    let name: String
    let image: String
}

struct ProductLine: Codable {
    let name: String
    let image: String
    let products: [Product]?
}

struct CustomerCategory: Codable {
    let name: String
    let image: String
    let productLine: [ProductLine]?
}

Then you'd process the response like so:

func processResponse(_ data: Data) {
    struct ResponseObject: Codable {
        let success: Bool
        let errorCode: Int?
        let result: [CustomerCategory]?
    }

    do {
        let responseObject = try JSONDecoder().decode(ResponseObject.self, from: data)

        guard responseObject.success, let customerCategories = responseObject.result else {
            // handle server error here
            return
        }

        print(customerCategories)
    } catch {
        print(error)
    }
}

This allows you to add new customer categories (eg children) or product lines (eg things other than jeans) without affecting the basic interface with the server.


In your other question , you've changed the nature of the data being returned, but, again, I'd advise against putting data attributes in the keys of your dictionaries.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM