Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 4.1 JSON的解析部分_Json_Swift_Parsing_Decodable - Fatal编程技术网

Swift 4.1 JSON的解析部分

Swift 4.1 JSON的解析部分,json,swift,parsing,decodable,Json,Swift,Parsing,Decodable,我是Swift的新手,希望利用可解码功能,希望能得到一些帮助 我正在使用的公共API会在键“c”下发出我想要的数据,但它周围有一些元数据。例如: { a: 1, b: 2, c: [{ d: 3, e: 4 }, { d: 5, e: 6 } ] } 我创建了这样一个结构: struct Block: Decodable { d: Int? e: Int? } 如上所述,我希望能够尽快(抱歉)

我是Swift的新手,希望利用可解码功能,希望能得到一些帮助

我正在使用的公共API会在键“c”下发出我想要的数据,但它周围有一些元数据。例如:

{
  a: 1,
  b: 2,
  c: [{
      d: 3,
      e: 4
    },
    {
      d: 5,
      e: 6
    }
  ]
}
我创建了这样一个结构:

struct Block: Decodable {
   d: Int?
   e: Int?
}
如上所述,我希望能够尽快(抱歉)将数据从“c”下的数据解析为类型:
[Block]
,并希望有一种4.1的方法来实现这一点

谢谢你的时间

我认为最简单(最快速)的方法就是创建两个结构

struct BlockResponse: Decodable {
  let c: [Block]
}

struct Block: Decodable {
  let d: Int?
  let e: Int?
}
然后

let result = try decoder.decode(BlockResponse.self, from: jsonResponse)
编辑: 您也可以像这里一样省略
BlockResponse

通过将扩展名与keyPath一起使用:

extension JSONDecoder {
  func decode<T: Decodable>(_ type: T.Type, from data: Data, keyPath: String) throws -> T {
      let toplevel = try JSONSerialization.jsonObject(with: data)
      if let nestedJson = (toplevel as AnyObject).value(forKeyPath: keyPath) {
          let nestedJsonData = try JSONSerialization.data(withJSONObject: nestedJson)
          return try decode(type, from: nestedJsonData)
      } else {
          throw DecodingError.dataCorrupted(.init(codingPath: [], debugDescription: "Nested json not found for key path \"\(keyPath)\""))
      }
  }
}



try decoder.decode([Block].self, from: data, keyPath: "c")
扩展JSONDecoder{ func decode(uType:T.type,from data:data,keyPath:String)抛出->T{ 让toplevel=try JSONSerialization.jsonObject(with:data) 如果让nestedJson=(顶级为AnyObject).value(forKeyPath:keyPath){ 让nestedJsonData=try JSONSerialization.data(withJSONObject:nestedJson) 返回try decode(类型,from:nestedJsonData) }否则{ 抛出DecodingError.dataCorrupted(.init(codingPath:[],debugDescription:“未找到密钥路径\”(密钥路径)\“”)的嵌套json) } } } 尝试解码器。解码([Block].self,发件人:数据,密钥路径:“c”)
所以你想省略a:1,b:2?@Piotralabunski是的。我只是想知道最好的方法。谢谢,我的印象是结构必须与json格式完全匹配,不知道可以省略字段!这真的是最简单的方法吗?很多语言使这一步变得非常简单。为什么我要创建不必要的包装来保存业务数据,只是为了符合API,即使我永远不会在应用程序代码中使用该层次结构。。。。。它增加了项目的浪费和不必要的复杂性。Swift似乎会让你克服这些障碍……你可以使用带有keyPath的版本,而不需要额外的结构(参见编辑)。在我看来,你根本不应该向你的移动客户端发送不必要的数据。如果API不是由您控制的,您可以创建一个中间件来调整移动客户端的数据。