将JSON解析为正确的结构格式。

huangapple go评论69阅读模式
英文:

Parsing JSON into a correct struct format

问题

I will provide translations for the non-code parts of your text:

"Being pretty new to swiftUI development and don't understanding much at the moment I am sorry if this question have already been answered but I couldn't find (or at least understand) anything to solve my problem. To practice, I am trying to create a first app, a flag quizz. While probably being very easy to do, I am having a hard time trying to answer these two questions:

  1. What would be the best solution to store the flag images? Would it be in the asset folder, trying to retrieve them from an API, or storing them in a free backend service like Firebase if I need to create more functionalities for the app?

  2. I went for the API solution on my side, but I am struggling to get it properly done. I'd like to have an array of "Flag" structs allowing me to randomly pick a "Flag" to be displayed in the view with its associated "shortName" (to retrieve the correct flag from the URL) and "Name." Here is what I have so far:

The JSON file provided by the website is following this format:

With the dictionary created, I'd like to assign the CodingKey to "shortName" and the value of the CodingKey to "name" in order for the link to be correctly initialized once I request a random question from the view.
I'm pretty sure this is definitely not the best way to do it, but as a true beginner, working a little bit with a JSON file can help me a lot.

Many thanks for any help you can provide!"

Please let me know if you need any further assistance.

英文:

Being pretty new to swiftUI development and don't understanding much at the moment I am sorry if this question have already been answered but I couldn't find (or at least understand) anything to solve my problem. To practice, I am trying to create a first app, a flag quizz. While probably being very easy to do, I am having a hard time trying to answer these two questions :

  1. What would be the best solution to store the flag images ? Would in it be in the asset folder, trying to retrieve them from an API or storing them in a free backend service as Firebase if I need to create more functionalities to the app ?

  2. I went for the API solution on my side but I am struggling to get it properly done. I'd like to have an array of "Flag" structs allowing me to randomly pick a "Flag" to be displayed in the view with its associated "shortName" (to retrieve the correct flag from the URL) and "Name". Here is what I have so far :


import Foundation

let decoder = JSONDecoder()

struct Flag: Codable, Identifiable {
    var flagLink: String
    var flagDetails: FlagDetails
    var id = UUID()
    
    init(flagLink: String, flagDetails: FlagDetails) {
        self.flagDetails = flagDetails
        self.flagLink = "https://flagcdn.com/w320/\(flagDetails.shortName).png"
    }
}

struct FlagDetails: Codable {
    var shortName: String
    var name: String
}


func getJSON(){
    
    guard let urlJSON = URL(string: "https://flagcdn.com/fr/codes.json") else {
        print("Invalid URL")
        return
    }
    URLSession.shared.dataTask(with: urlJSON) { (data, response, error) -> Void in
        if error == nil && data != nil {
            do {
                let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [String: Any]
                print()
    
            } catch {
                print("Invalid data: \(error)")
            }
        }
    }.resume()
}

The JSON file provided by the website is following this format :

{
    "ad": "Andorra",
    "af": "Afghanistan",
    "ag": "Antigua-et-Barbuda",
    "ai": "Anguilla"
}

With the dictionary created, I'd like to assign the CodingKey to "shortName" and the value of the CodingKey to "name" in order for the link to be correctly initialized once I request a random question from the view.
I'm pretty sure this is definitely not the best way to do it but as a true beginner, working a little bit with JSON file can help me a lot.

Many thanks for any help you can provide !

答案1

得分: -1

  1. 我会使用一个框架来下载图片,比如Kingfisher或ImageLoaderSwift。

  2. 至于回答你的第二个问题:

你可以循环遍历字典,使用 for KEY in DICTIONARY,然后将值添加到一个数组 (countryFlags) 中。

只有在你能直接将JSON字符串转换为结构体时才需要Codable,但在这种情况下是不行的,因为你需要一个数组而不是一个字典。

请注意,我不在Mac上,所以无法测试这段代码。

struct Flag {
  //.../

  // 简化的构造函数
  init(shortName: String, name: String) {
      self.flagDetails = FlagDetail(shortName: shortName, name: name)
      self.flagLink = "https://flagcdn.com/w320/\(shortName).png"
  }
}

struct FlagDetails {
    //.../
}

var countryFlags = [Flag]()

func getJSON(){
    
    guard let urlJSON = URL(string: "https://flagcdn.com/fr/codes.json") else {
        print("无效的URL")
        return
    }

    URLSession.shared.dataTask(with: urlJSON) { (data, response, error) -> Void in
        if error == nil && data != nil {
            do {
                // 将 [String: Any] 更改为 [String: String]
                let countryDictionary = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [String: String]

                // 新代码
                for (shortName, name) in countryDictionary {
                  countryFlags.append(Flag(shortName: shortName, name: name))
                }

                print(countryFlags)

            } catch {
                print("无效的数据: \(error)")
            }
        }
    }.resume()
}
英文:
  1. I would use a framework to download the images, like Kingfisher or ImageLoaderSwift.

  2. As for answering your second question:

You can loop through the dictionary, using for KEY in DICTIONARY, and then add values to an array (countryFlags).

You only need Codable if you can directly convert a json string to a struct, which you can't in this case, because you need an array and not a dictionary.

Mind you, I'm not on a Mac, so I can't test the code.

struct Flag {
  /.../

  // Simplified constructor for you
  init(shortName: String, name: String) {
      self.flagDetails = FlagDetail(shortName: shortName, name: name)
      self.flagLink = "https://flagcdn.com/w320/\(shortName).png"
  }
}

struct FlagDetails {
    /.../
}

var countryFlags = [Flag]()

func getJSON(){
    
    guard let urlJSON = URL(string: "https://flagcdn.com/fr/codes.json") else {
        print("Invalid URL")
        return
    }

    URLSession.shared.dataTask(with: urlJSON) { (data, response, error) -> Void in
        if error == nil && data != nil {
            do {
                // Changed [String: Any] to [String: String]
                let countryDictionary = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [String: String]

                // NEW CODE
                for (shortName, name) in countryDictionary {
                  countryFlags.append( Flag(shortName: shortName, name: name) )
                }

                print(countryFlags)

            } catch {
                print("Invalid data: \(error)")
            }
        }
    }.resume()
}

huangapple
  • 本文由 发表于 2023年4月10日 22:57:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/75978180.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定