繁体   English   中英

JSON转换成自定义对象的数组(Swift)

[英]JSON into array of custom objects (Swift)

我有一个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 }

如何以最佳方式过滤它?

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

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

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

现在,真正的问题似乎是您希望内部拥有与JSON接收的不同的结构,包括诸如“每个categoryID只有一个”之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
}

国家杰森

{
      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)
    }

  }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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