英文:
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:
- 
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?
 - 
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 :
- 
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 ?
 - 
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
- 
我会使用一个框架来下载图片,比如Kingfisher或ImageLoaderSwift。
 - 
至于回答你的第二个问题:
 
你可以循环遍历字典,使用 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()
}
英文:
- 
I would use a framework to download the images, like Kingfisher or ImageLoaderSwift.
 - 
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()
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论