我有一个名为 ObjectAPIModel 的类型,它明确符合 Codable 协议。我还有一个函数,它接收一些数据并调用另一个函数将任何 JSON 解码为指定类型。但是如果我调用decodeJSON(),它会显示一个错误,指出ObjectAPIModel 不符合Decodable。有人可以帮忙吗?
struct ObjectAPIModel: Codable {
let objectID: Int
var primaryImage: String
var title: String
var department: String
}
Run Code Online (Sandbox Code Playgroud)
func decodeJSON<T: Decodable>(data: Data, ofType: T) -> Result<T, APIError> {
let decodedObject = try? JSONDecoder().decode(T.self, from: data)
if decodedObject == nil {
return .failure(APIError.emptyResponse)
} else {
return .success(decodedObject!)
}
}
Run Code Online (Sandbox Code Playgroud)
let result = decodeJSON(data: unwrappedData, ofType: ObjectAPIModel)
Run Code Online (Sandbox Code Playgroud)
我收到错误:“类型‘ObjectAPIModel.Type’不能符合‘Decodable’”
我如何使用Codable解码JSON并在创建对象(而不是结构)时交叉引用它们?在这个例子中,我希望Painting该类具有Color在JSON中定义的对象数组.(我也希望能够将它们编码回JSON.)
额外奖励:在这种情况下,我宁愿选择Painting.colors非可选let属性而不是 var.我不希望它在创作后改变,我不希望它永远是零.(我宁愿使用空数组的默认值而不是nil.)
class Art: Codable {
var colors: [Color]?
var Paintings: [Painting]?
}
class Color: Codable {
var id: String?
var hex: String?
}
class Painting: Codable {
var name: String?
var colors: [Color]?
}
let json = """
{
"colors": [
{"id": "black","hex": "000000"
},
{"id": "red", "hex": "FF0000"},
{"id": "blue", "hex": "0000FF"},
{"id": "green", "hex": "00FF00"},
{"id": "yellow", "hex": "FFFB00"},
{"id": "orange", "hex": "FF9300"},
{"id": …Run Code Online (Sandbox Code Playgroud) 我从API获得响应,但问题是API将值作为一串日期和双精度发回.因此我收到错误"预期解码Double但发现字符串/数据".我已经构建了这样的结构来解决问题,但这似乎是一个补丁.有没有更好的方法来解决这个问题?我觉得苹果已经想到了这一点,并包含一些原生的东西来解决这个问题.
struct SimpleOrder:Codable{
var createdDate:Date! {
return createdDateString.dateFromISO8601
}
var createdDateString:String
var orderId:String!
var priceVal:Double!
var priceString:String{
didSet {
priceVal = Double(self.priceString)!
}
}
private enum CodingKeys: String, CodingKey {
//case createdDate
case createdDateString = "time"
case orderId = "id"
case priceVal
case priceString = "price"
}
}
Run Code Online (Sandbox Code Playgroud)
我不知道这是否相关,但这就是它的使用方式.我将数据作为字符串获取并将其转换为存储在dataFromString变量中的数据
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601 //This is irrelevant though because the date is returned as a string.
do{
let beer = try decoder.decode(SimpleOrder.self, from: dataFromString)
print ("beer …Run Code Online (Sandbox Code Playgroud) 寻找一些关于如何处理我最近遇到的场景的输入.
我一直在使用Swift 4s Codable成功,但今天发现了一个我没想到的崩溃.我正在使用的API表示它返回了一个boolean密钥manage_stock.
我的存根结构看起来像:
struct Product: Codable {
var manage_stock: Bool?
}
Run Code Online (Sandbox Code Playgroud)
这很好用,问题是API 有时会返回string而不是a boolean.
因此,我的解码失败了:
Expected to decode Bool but found a string/data instead.
Run Code Online (Sandbox Code Playgroud)
字符串只有等于"parent",我希望它等于false.
我也可以更改我的结构,var manage_stock: String?如果这样可以更容易地从API中获取JSON数据.但是,当然,如果我改变了,我的错误只会改为:
Expected to decode String but found a number instead.
Run Code Online (Sandbox Code Playgroud)
是否有一种简单的方法来处理这种突变,或者我是否需要丢失所有Codable带来的自动化并实现我自己的init(decoder: Decoder).
干杯
我有一个带有响应主体的JSON,如下所示:
{
"Count": 116,
"Message": "Result returned successfully",
"SearchCriteria": "Search Criteria",
"Results": [
{
"Value": "",
"ValueId": "",
"Variable": "Suggested VIN",
"VariableId": 142
},
< 115 more like this >
]
}
Run Code Online (Sandbox Code Playgroud)
我最初尝试创建编码密钥,如下所示:
struct ResponseBody: Codable {
var count: Int
var message: String
var searchCriteria: String
var results: [Result]
enum ResponseKeys: String, CodingKey {
case count = "Count"
case message = "Message"
case searchCriteria = "SearchCriteria"
case results = "Results"
}
}
struct Result: Codable {
var value: String? …Run Code Online (Sandbox Code Playgroud) 我使用API来解析一些数据 - 这很有效.但是现在api使用了像"d/a"和"test%"这样的名字,我无法用这个符号创建一个可编码的结构.有没有办法使用它们?
提前致谢
首先,很抱歉问题标题不清楚
我正在制作一个可编码的结构,它将用作json消息。
enum MessageType: String, Codable{
case content
case request
case response
}
struct Message: Codable{
var type: MessageType
var content: /* NEED HELP HERE */
}
struct Content: Codable {...}
struct Request: Codable {...}
struct Response: Codable {...}
Run Code Online (Sandbox Code Playgroud)
声明Message(如果type是)时content,其content类型应为Content。
let message = Message(
type: .content,
content: Content( ... )
}
Run Code Online (Sandbox Code Playgroud)
当type为is时request,其content类型应为Request。
let message = Message(
type: .request,
content: Request( ... ) …Run Code Online (Sandbox Code Playgroud) Swift as Codable(Decodable&Encodable)协议的这种功能非常有用。但我发现了这样的问题:让我们让Parent类符合Codable:
class Parent: Codable {
var name: String
var email: String?
var password: String?
}
Run Code Online (Sandbox Code Playgroud)
好的,该类符合“从盒子开始”的Codable协议,您无需编写任何初始化程序,就可以像这样从JSON进行初始化:
{ "name": "John", "email": "johndoe@yahoo.com", "password": <null>}
Run Code Online (Sandbox Code Playgroud)
但假设我们需要其他类,Child从Parent继承并符合Codable:
class Child: Parent {
var token: String
var date: Date?
}
Run Code Online (Sandbox Code Playgroud)
因此,Child类必须通过与Parent保持一致,从而与Codable保持一致,Child类的BUT属性将无法从JSON正确初始化。我发现的决定是自己为Child类编写所有可编码内容,例如:
class Child: Parent {
var token: String
var date : Date?
enum ChildKeys: CodingKey {
case token, date
}
required init(from decoder: Decoder) throws {
try super.init(from: decoder)
let container = try decoder.container(keyedBy: ChildKeys.self)
self.token …Run Code Online (Sandbox Code Playgroud) 我有一个函数调用URL来接收数据作为JSON.要将JSON解码为自定义类,我使用JSONDecoder.
fileprivate func loadFlux<T>(_ typeClass: T.Type, urlCriteria url: String) -> Promise<Any> {
var dataFlux: [T]? = nil
var promise: Promise<Any>? = nil
...
let jsonData: Data = try! JSONSerialization.data(withJSONObject: data as! NSArray)
let decoder = JSONDecoder()
dataFlux = try decoder.decode([T], from: data)
...
}
Run Code Online (Sandbox Code Playgroud)
在安装最新版本的Xcode和swift 4.2之前,代码构建没有任何问题.
但现在我收到以下错误消息:Type 'T' does not conform to protocol 'Decodable'在线:
dataFlux = try decoder.decode([T], from: data)
Run Code Online (Sandbox Code Playgroud)
我试图谷歌搜索消息,但现在没有任何成功.有什么建议可以解决这个问题吗?
我正在尝试将以下JSON解码为可编码对象。
[
{
"Action": "CREDIT",
"Status": 1,
"TransactionDate": "2019-09-20T04:23:19.530137Z",
"Description": "test"
},
{
"Action": "CREDIT",
"Status": 1,
"TransactionDate": "2019-09-20T04:23:19.530137Z",
"Description": "test"
},
{
"Action": "CREDIT",
"Status": 1,
"TransactionDate": "2019-09-20T04:23:19.530137Z",
"Description": "test"
}
]
Run Code Online (Sandbox Code Playgroud)
我的可编码类是..
struct UserWalletHistoryList: Codable {
var historyList: [UserWalletHistory]
}
struct UserWalletHistory: Codable{
var Action: String?
var Status: Int?
var TransactionDate: String?
var Description: String?
}
Run Code Online (Sandbox Code Playgroud)
但这并不成功。我认为这是因为变量名historyList,因为没有像historyListJSON 这样的键。那...那应该是什么?