代码之家  ›  专栏  ›  技术社区  ›  Godfather

Swift:可解码

  •  2
  • Godfather  · 技术社区  · 6 年前

    假设我有一个API请求中的json:

    friends: {  
       "john":31,
       "mark":27,
       "lisa":17,
       "tom":41
    }
    

    friends: [  
       { "john":31 },
       { "mark":27 },
       { "lisa":17 },
       { "tom":41 }
    ]
    

    但是API并没有以这种方式提供结果。最后我想把它映射到一个[Friend]数组,Friend是:

    class Friend: Decodable {
      let name: String
      let age: Int
    }
    

    我应该如何序列化这个json来获得[Friend]?

    2 回复  |  直到 6 年前
        1
  •  4
  •   Maxim Kosov    6 年前

    首先,这个示例根本不是有效的json。为了有效,它要么不应该包含“friends”标签,要么应该嵌入像这样的另一个对象中

    {
      "friends": {  
        "john":31,
        "mark":27,
        "lisa":17,
        "tom":41
      }
    }
    

    如果我正确理解了这个问题,您需要将json对象解码为swift数组。我不认为有一种方法可以不写自定义解码。相反,您可以将json解码为 Dictionary 当手动绘制它时

    struct Friend {
        let name: String
        let age: Int
    }
    
    struct Friends: Decodable {
        let friends: [String: Int]
    }
    
    let friends = try! JSONDecoder().decode(Friends.self, from: json.data(using: .utf8)!)
        .friends
        .map { (name, age) in Friend(name: name, age: age) }
    
        2
  •  0
  •   user28434'mstep    6 年前

    免责声明 @scriptable's answer (我回答时删除了,嗯),在哪里 name age

    但如果你不能或不想改变它,你可以用这样的东西来解码你的密码 Friend 类型:

    struct Friend: Decodable {
        let name: String
        let age: UInt
    
        init(from decoder: Decoder) throws {
            let container = try decoder.singleValueContainer()
            let dictionary = try container.decode([String: UInt].self)
    
            guard dictionary.count == 1, let (name, age) = dictionary.first else {
                throw DecodingError.invalidFriendDictionary
            }
    
            self.name = name
            self.age = age
        }
    
        enum DecodingError: Error {
            case invalidFriendDictionary
        }
    }
    
    struct Friends: Decodable {
       let friends: [Friend]
    }
    
    let friends = try JSONDecoder().decode(Friends.self, from: data)
    

    它假设 key 名称 value 年龄 . 并检查是否只有一对需要解析。