【问题标题】:JSON into array of custom objects (Swift)JSON 到自定义对象数组 (Swift)
【发布时间】:2019-02-23 18:39:36
【问题描述】:

我有一个 JSON,我需要它来将它转换为对象数组。 这是我的 JSON(它的简短版本)

[
{
    "categoryID": 5,
    "categoryDescription": "Trips",
    "groupID": 43,
    "groupDescription": "USA",
    "groupImage": "e613c87a-4dab-4929-90cf-2b584fdf0399.jpg",
    "subgroupDescription": "2 days",
    "subgroupPrice": "200"
},
{
   "categoryID": 5,
    "categoryDescription": "Trips",
    "groupID": 43,
    "groupDescription": "USA",
    "groupImage": "e613c87a-4dab-4929-90cf-2b584fdf0399.jpg",
    "subgroupDescription": "5 days",
    "subgroupPrice": "500"
},
{
    "categoryID": 5,
    "categoryDescription": "Trips",
    "groupID": 33,
    "groupDescription": "Mexico",
    "groupImage": "e613c87a-4dab-4929-90cf-2b584fdf0399.jpg",
    "subgroupDescription": "3 days",
    "subgroupPrice": "400"
},
{
    "categoryID": 5,
    "categoryDescription": "Trips",
    "groupID": 33,
    "groupDescription": "Mexico",
    "groupImage": "e613c87a-4dab-4929-90cf-2b584fdf0399.jpg",
    "subgroupDescription": "1 days",
    "subgroupPrice": "150"
},
{
    "categoryID": 3,
    "categoryDescription": "Hotels",
    "groupID": 22,
    "groupDescription": "My Hotel",
    "groupImage": "e613c87a-4dab-4929-90cf-2b584fdf0399.jpg",
    "subgroupDescription": "1 night",
    "subgroupPrice": "50"
},
{
    "categoryID": 3,
    "categoryDescription": "Hotels",
    "groupID": 10,
    "groupDescription": "Your Hotel",
    "groupImage": "e613c87a-4dab-4929-90cf-2b584fdf0399.jpg",
    "subgroupDescription": "2 nights",
    "subgroupPrice": "150"
}]

我需要像这样创建一个自定义对象:(如何在 Swift 4 中创建这样的对象?)

在 JSON 中,我们有 categoryIDgroupID 我需要根据它们过滤数组,例如我只需要一个 categoryID 为 5 的对象。我需要只有一个 groupID 为 43 的对象。但我需要所有子组。 这是我的对象的结构:(我不知道我是否走在正确的道路上)

struct Categories {
var categoryID: NSNumber
var categoryDescription: String
var groups : [Groups]}

struct Groups {
var geoupID: NSNumber
var geoupDescription: String
var groupImage: String
var subGroups : [Subgroups] }

struct Subgroups {
var subgroupPrice: NSNumber
var subgroupDescription: String }

我怎样才能以最好的方式过滤它?

【问题讨论】:

    标签: ios arrays json swift swift4


    【解决方案1】:

    至于如何制作结构,只需使用Decodable 并根据您在JSON 中的期望命名字段,或者使用CodingKeys 指定名称。例如:

    struct MyStruct: Decodable {
        let categoryID: Int
        let categoryDescription: String
        let groupID: Int
        // …
    }
    

    然后您可以使用JSONDecoder 将结果解码为[MyStruct]

    现在,真正的问题似乎是您希望在内部拥有与您收到的 JSON 不同的结构,包括“每个 categoryID 中只有一个”这样的约束。可能最直接的方法是遍历解码结果并将内容复制到不同的结构中。

    除了数组(例如,var groups: [Groups]),您还可以使用带有 groupID 作为键的字典来强制每个 id 只有一个,例如:

    guard let results = try? jsonDecoder.decode([MyStruct].self, from: json) else { return }
    var categories = [Int: Category]()
    for result in results {
        // fetch existing category or make a new one
        var category = categories[result.categoryID, default: Category(id: result.categoryID, description: result.categoryDescription)]
    
        // fetch existing group in category or make a new one
        var group = category.groups[result.groupID, default: Group(id: result.groupID, description: result.groupDescription, image: result.groupImage)]
    
        // append subgroup (always new since there is no id)
        let subgroup = Subgroup(description: result.subgroupDescription, price: result.subgroupPrice)
        group.subgroups.append(subgroup)
    
        // "save"
        category.groups[result.groupID] = group
        categories[result.categoryID] = category
    }
    

    【讨论】:

    • 请注意,我只使用Decodable,因为它似乎是一种一次性的中间格式就足够了,但您也可以使用Codable(添加Encodable)。
    • 感谢您的回复,我之前尝试过,但我对“子组”和“组”有疑问,我是否必须在“for 循环”中初始化组?您能更清楚地了解组和子组吗???
    • @Sattar 创建Category 时将groups 设为空字典,创建Group 时将subgroups 设为空数组,然后修改其他数组。请参阅编辑后的答案(未经测试的代码,但想法应该很清楚)。
    • 顺便说一句,如果你也可以影响 JSON 方面的事情,那么现在它是非常次优的,因为它为每个子组返回重复的类别和组 - 如果你在 JSON 中有类似的嵌套结构,结果会小得多,您可以将它们直接解码为最终结构。
    • 谢谢,您更新的答案很有效,我知道这应该由服务器端程序员完成,几天前我要求他们以正确的格式向我发送数据,但他们没有所以我决定在应用程序方面做,无论如何感谢您的帮助。
    【解决方案2】:

    国家 Json

    {
          ID = 2;
          Image = "";
          Name = "";
          City =     (
            {
              ID = 74;
              Name = "";
              ParentID = 2;
          },
            {
              ID = 79;
              Image = "";
              Name = Other;
              ParentID = 2;
          }
          );
        },
        {
          ID = 31;
          Image = "";
          Name = "";
          City =     (
            {
              ID = 99;
              Name = "";
              ParentID = 31;
          },
            {
              ID = 100;
              Name = "";
              ParentID = 31;
          });
        }
    

    我的班级

    class Country: Codable {
    
        var id: String?
        var image: String?
        var name: String?
        var cityList: [City]?
    
        enum CodingKeys: String, CodingKey {
          case id = "ID"
          case image = "Image"
          case name = "Name"
          case city = "City"
        }
    
        required init(from decoder: Decoder) throws {
          let values = try decoder.container(keyedBy: CodingKeys.self)
    
          id = try? values.decode(String.self, forKey: .id)
          image = try? values.decode(String.self, forKey: .image)
          name = try? values.decode(String.self, forKey: .name)
          cityList = try? values.decode([City].self, forKey: .city)
        }
    
        func encode(to encoder: Encoder) throws {
          var container = encoder.container(keyedBy: CodingKeys.self)
          try container.encode(id, forKey: .id)
          try container.encode(image, forKey: .image)
          try container.encode(name, forKey: .name)
          try container.encode(cityList, forKey: .city)
        }
    
      }
    
      class City: Codable {
    
        var id: String?
        var name: String?
        var parentId: String?
    
        enum CodingKeys: String, CodingKey {
          case id = "ID"
          case name = "Name"
          case parentId = "ParentID"
        }
    
        required init(from decoder: Decoder) throws {
          let values = try decoder.container(keyedBy: CodingKeys.self)
          id = try? values.decode(String.self, forKey: .id)
          name = try? values.decode(String.self, forKey: .name)
          parentId = try? values.decode(String.self, forKey: .parentId)
        }
    
        func encode(to encoder: Encoder) throws {
          var container = encoder.container(keyedBy: CodingKeys.self)
          try container.encode(id, forKey: .id)
          try container.encode(name, forKey: .name)
          try container.encode(parentId, forKey: .parentId)
        }
    
      }
    

    【讨论】:

      猜你喜欢
      • 2023-03-12
      • 2023-04-02
      • 1970-01-01
      • 2018-05-14
      • 2019-07-28
      • 2012-10-10
      • 2019-12-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多