使用 SwiftyJSON 反序列化时如何添加对象数组

Posted

技术标签:

【中文标题】使用 SwiftyJSON 反序列化时如何添加对象数组【英文标题】:How to add arrays of objects when deserializing with SwiftyJSON 【发布时间】:2019-12-30 21:47:17 【问题描述】:

我正在使用 SwiftyJSON 和 Swift 5.1 反序列化 JSON。

我有如下一组数据

"name": "American Standard",
            "number": 1,
            "subcategories": [
                
                    "name": "American Light Lager",
                    "letter": "A",
                    "guidelines": 
                        "overallImpression": "Some String",
                        "aroma": "Some String",
                        "appearance": "Some String",
                        "flavor": "Some String",
                        "mouthfeel": "Some String",
                        "comments": "Some String",
                        "history": "Some String",
                        "ingredients": "Some String",
                        "comparison": "Some String",
                        "vitalStatistics": 
                            "og": "1.028 - 1.040",
                            "fg": "0.998 - 1.008",
                            "abv": "2.8 - 4.2%",
                            "ibu": "8 - 12",
                            "srm": "2 - 3"
                        
                   ,
                   "commercialExamples": [
                       
                            "name": "name1"
                        ,
                        
                            "name": "name2"
                        ,
                        
                            "name": "name3"
                        ,
                    ],
                    "tags": [
                        
                            "tag": "tag1"
                        ,
                        
                            "tag": "tag2"
                        ,
                    ]
                ,

我使用struct来保存所有数据,如下所示。

struct Beers

    var name: String
    var number: Int
    var subcategories: Subcategory


struct Subcategory

    var name: String
    var letter: String
    var guidelines: Guidelines
    var commercialExamples: [CommercialExample]
    var tags: [Tag]


struct Guidelines

    var overallImpression: String
    var aroma: String
    var appearance: String
    var flavor: String
    var mouthfeel: String
    var comments: String
    var history: String
    var ingredients: String
    var comparison: String
    var vitalStatistics: VitalStatistics


struct VitalStatistics

    var og: String
    var fg: String
    var abv: String
    var ibu: String
    var srm: String


struct CommercialExample : Hashable

    var name: String
    func hash(into hasher: inout Hasher)
    
        hasher.combine(name)
    


struct Tag : Hashable

    var tag: String
    func hash(into hasher: inout Hasher)
    
        hasher.combine(tag)
    

对于我的反序列化代码,我有这个。

for (index, dict) in jsonObject

    let thisBeer = Beers(name: dict["name"].stringValue, number: dict["number"].intValue, subcategories: Subcategory(name: dict["name"].stringValue, letter: dict["letter"].stringValue, guidelines: Guidelines(overallImpression: dict["overallImpression"].stringValue, aroma: dict["aroma"].stringValue, appearance: dict["appearance"].stringValue, flavor: dict["flavor"].stringValue, mouthfeel: dict["mouthfeel"].stringValue, comments: dict["comments"].stringValue, history: dict["history"].stringValue, ingredients: dict["ingredients"].stringValue, comparison: dict["comparison"].stringValue, vitalStatistics: VitalStatistics(og: dict["og"].stringValue, fg: dict["fg"].stringValue, abv: dict["abv"].stringValue, ibu: dict["ibu"].stringValue, srm: dict["srm"].stringValue)), commercialExamples: CommercialExample(name: dict["name"].stringValue), tags: Tag(tags: dict["tags"].stringValue)))
    beers.append(thisBeer)

这就是我卡住的地方。我更熟悉 C# 和 .net。我只是不知道如何遍历商业示例和标签,并从数据中创建对象并用它们填充数组。使用 Swift 和 SwiftyJSON 的正确方法是什么?

【问题讨论】:

忘记SwiftyJSON,转而使用Codable。它将 JSON 解析为结构,无需任何额外代码。 【参考方案1】:

您必须首先使用 JSONSerializable 协议将您的 JSON 数据解码为对象。例如在你的情况下:

struct Beers: JSONSerializable 
var name: String?
var number: Int?
var subcategories: Subcategory?

   enum CodingKeys: String, CodingKey 
      case name
      case number
      case subcategories
   


extension Beers: Decodable 
init(from decoder: Decoder) throws 
    let values = try decoder.container(keyedBy: CodingKeys.self)
    if let value = try values.decodeIfPresent(String?.self, forKey: .name) 
        if let value = value 
            name = value
        
    
    if let value = try values.decodeIfPresent(Int?.self, forKey: .number) 
        if let value = value 
            number = value
        
    
    if let value = try values.decodeIfPresent(Subcategory?.self, forKey: .subcategories) 
        if let value = value 
            subcategories = value
        
     
   

然后你可以像这样从 JSON 数据中创建一个对象:

do 
        let model = try JSONDecoder().decode(Beers.self, from: jsonData)
     catch let error 
        print(error)
    

【讨论】:

以上是关于使用 SwiftyJSON 反序列化时如何添加对象数组的主要内容,如果未能解决你的问题,请参考以下文章

将 JSON 响应保存为变量以使用 SwiftyJSON 反序列化

SwiftyJSON 添加 JSON 对象数组

反序列化时如何正确测试数据类型

反序列化时如何从json中删除k__BackingField

C#中如何实现多个观测数据对象序列化和反序列化?

如何在 Greenplum/Postgres 中使用 PL/R 反序列化模型对象?