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

时间:2018-09-19 14:36:40

标签: ios arrays json swift swift4

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

document.querySelector('.ResRoom .infoIcoAfter').innerHTML;

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

enter image description here

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

[
{
    "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"
}]

如何最好地过滤它?

2 个答案:

答案 0 :(得分:2)

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

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

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

现在,真正的问题似乎是您希望内部拥有与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
}

答案 1 :(得分:0)

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

  }