我有以下数据结构:
{
"type": "foo"
"data": { /* foo object */ }
}
Run Code Online (Sandbox Code Playgroud)
这是我的解码它的类:
final public class UntypedObject: Decodable {
public var data: Data
enum UntypedObjectKeys: CodingKey {
case data
}
required public init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: UntypedObjectKeys.self)
self.data = try values.decode(Data.self, forKey: .data)
}
}
Run Code Online (Sandbox Code Playgroud)
我正在获取这样的对象数组,这就是我解码它的方式:
let decoder = JSONDecoder()
let objectList = try decoder.decode([UntypedObject].self, from: data)
Run Code Online (Sandbox Code Playgroud)
但是我在控制台中收到此错误:
typeMismatch(Swift.Array,Swift.DecodingError.Context(codingPath:[Foundation.(_ JSONKey in _12768CA107A31EF2DCE034FD75B541C9)(stringValue:"Index 0",intValue:Optional(0)),Playground_Sources.UntypedObject.UntypedObjectKeys.data],debugDescription:"期望解码数组但是找到了一个字典.",underlyingError:nil))
所以问题是可以将正确的JSON对象解码为Data类型属性,如果是这样的话 - 我该如何实现呢?
我正在使用Rest API服务,在该服务中,响应分为基本响应,所有其他响应都从该继承。
我正在尝试使用Decoder接口为响应模型类构建相同的结构。
但是我在解码继承的类时遇到问题。
我试图解决此问题: 在带有继承的Swift 4中使用Decodable
但是没有运气。
这是初始结构:
class LoginResponse: BaseResponse{
var Message: String?
private enum CodingKeys: String, CodingKey{
case Message
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
Message = try container.decode(String.self, forKey: .Message)
let superDecoder = try container.superDecoder()
try super.init(from: superDecoder)
}
}
class BaseResponse: Decodable {
var Status: Int?
private enum CodingKeys: String, CodingKey{
case Status
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self) // This …Run Code Online (Sandbox Code Playgroud) 我在优雅地处理这个错误时遇到了问题debugDescription: "Expected String value but found null instead."
我知道在我的结构中符合Codable,我的存储属性需要声明为可选字符串,正如我在这篇文章中读到的
我试过了,仍然出现错误。我还在那篇文章中读到,我还可以自定义解码器以将 nil 替换为空字符串。我不知道如何做到这一点。
这是我的代码:
struct Discover: Codable {
var page: Int
var totalResults: Int
var totalPages: Int
var results: [DiscoverResults]
enum CodingKeys: String, CodingKey {
case page
case totalResults = "total_results"
case totalPages = "total_pages"
case results = "results"
}
}
struct DiscoverResults {
var title: String
var releaseDate: String
var posterPath: String?
var id: Int
var genreIds: [Int]
var poster: UIImage?
enum CodingKeys: String, …Run Code Online (Sandbox Code Playgroud) 我想在Swift Coding / Encoding功能完成对JSON的解码后做一些初始化逻辑。
struct MyStruct: Codable {
let id: Int
var name: String
init() {
name = "\(id) \(name)"
}
}
Run Code Online (Sandbox Code Playgroud)
但是我得到了编译器错误:
Return from initializer without initializing all stored properties
Run Code Online (Sandbox Code Playgroud)
这对我很清楚,因为init()希望我初始化所有属性。但是添加具有所有必需属性的init()并不能解决该问题,因为当Codable插入时,此初始化器不会被调用(!):
init(id: Int, name: String) {
// This initializer is not called if Decoded from JSON!
self.id = id
self.name = "\(id) \(name)"
}
Run Code Online (Sandbox Code Playgroud)
然而,在解码完成之后,是否有一种方法可以执行一些初始化逻辑,而无需为每个属性手动进行所有解码?因此无需每次都执行init(from decoder: Decoder)。在这个简短的示例中,我只有两个简单的属性,但是生产代码包含数千个属性。
谢谢。
我目前正在使用SWIFT 4中的Decodable解析JSON.
JSON格式如下:
{
"autopayout_from": "1.010",
"earning_24_hours": "9.74731104",
"error": false,
"immature_earning": 0.635593030875,
"last_payment_amount": "1.91238210",
"last_payment_date": "Mon, 26 Feb 2018 15:08:02 GMT",
"last_share_date": "Mon, 26 Feb 2018 16:16:01 GMT",
"payout_daily": false,
"payout_request": false,
"total_hashrate": 109006.86,
"total_hashrate_calculated": 143855.75,
"transferring_to_balance": 0.2281390807,
"wallet": "0xbb76fc2ce36a19da28fd713e350a42f1023e2f7f",
"wallet_balance": "0.49556201",
"workers": {
"10003": {
"alive": false,
"hashrate": 0.0,
"hashrate_below_threshold": false,
"hashrate_calculated": 0.0,
"last_submit": "Mon, 26 Feb 2018 13:23:16 GMT",
"second_since_submit": 10612,
"worker": "10003"
},
"100151": {
"alive": false,
"hashrate": 0.0,
"hashrate_below_threshold": false,
"hashrate_calculated": 0.0,
"last_submit": "Mon, 26 Feb …Run Code Online (Sandbox Code Playgroud) 我有以下代码来提取编码密钥中包含的JSON:
let value = try! decoder.decode([String:Applmusic].self, from: $0["applmusic"])
Run Code Online (Sandbox Code Playgroud)
这成功处理了以下JSON:
{
"applmusic":{
"code":"AAPL",
"quality":"good",
"line":"She told me don't worry",
}
Run Code Online (Sandbox Code Playgroud)
但是,无法使用以下编码密钥提取JSON applmusic:
{
"applmusic":{
"code":"AAPL",
"quality":"good",
"line":"She told me don't worry",
},
"spotify":{
"differentcode":"SPOT",
"music_quality":"good",
"spotify_specific_code":"absent in apple"
},
"amazon":{
"amzncode":"SPOT",
"music_quality":"good",
"stanley":"absent in apple"
}
}
Run Code Online (Sandbox Code Playgroud)
数据模型applmusic,spotify并且amazon是不同的.但是,我只需要提取applmusic和省略其他编码密钥.
我的Swift数据模型如下:
public struct Applmusic: Codable {
public let code: String
public let quality: String
public let line: String
}
Run Code Online (Sandbox Code Playgroud)
API以完整的JSON响应,我不能要求它只给我所需的字段.
如何只解码json的特定部分?看起来,这Decodable …
无法理解为什么我的类不符合Codable请不要在我的情况下我不需要实现编码和解码方法.
public class LCLAdvantagePlusJackpotCache: Codable {
public let token: String
public let amount: NSNumber
public let member: Bool
public init(token: String, amount: NSNumber, member: Bool) {
self.token = token
self.amount = amount
self.member = member
}
enum CodingKeys: String, CodingKey {
case token, amount, member
}
}
Run Code Online (Sandbox Code Playgroud) 我有一个 JSON-API,它返回Courses. 它们Courses都有主键CourseLocations。我认为使用 解析所有内容并使用 更新它CourseTypes会很棒。CodableRealm().add(_:update:)
一切都很好。当 API 不返回完整的对象时就会出现问题。
这么说吧。API“/types”返回下面的数组,它包含创建或更新对象所需的所有数据。
[
{ "id": "1", "name": "Type 1", "sessions": 10, "sessionTime": 120.0 },
{ "id": "2", "name": "Type 2", "sessions": 5, "sessionTime": 20.0 }
]
Run Code Online (Sandbox Code Playgroud)
但随后我调用另一个 API 方法“/courses”,它返回一个课程信息以及对象“类型”,但不是全部,只是它的id和name:
[
{
"id": "0013",
"name": "Super cool course",
"type": { "id": "2", "name": "Type 2" }
}
]
Run Code Online (Sandbox Code Playgroud)
因此,当我为课程执行“add(_:update:)”时,我实际上更新了对象的所有值CourseType,而不仅仅是名称。结果,mysessions和sessionTimeproperty 被设置为 0。
我该如何避免呢?
这里有一个类供参考。
class …Run Code Online (Sandbox Code Playgroud) 我在Swift 4.2中遇到了JSON解析的问题.以下是显示运行时错误的以下代码.
我的Json数据如下所示,我从服务器获得.
{
code: 406,
message: "Email Address already Exist.",
status: 0
}
Run Code Online (Sandbox Code Playgroud)
我使用Codable来创建我的结构如下
struct Registration: Codable {
var code: Int
var status: Int
private enum CodinggKeys: String, CodingKey {
case code
case status
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
do {
self.code = Int(try container.decode(String.self, forKey: .code))!
} catch DecodingError.typeMismatch {
let value = try container.decode(Double.self, forKey: .code)
self.code = Int(value);
}
do {
self.status = try container.decode(Int.self, forKey: .status)
} …Run Code Online (Sandbox Code Playgroud) 我需要Decodable正确解码(协议)一个不精确的十进制值,从这个问题我了解如何正确处理十进制实例化,但是在解码时如何做到这一点?
如果尝试将任何数字初始化为字符串
if let value = try! container.decode(String.self, forKey: .d) {
self.taxAmount = Decimal(string: value)
}
Run Code Online (Sandbox Code Playgroud)
我明白了Fatal Error: "Expected to decode String but found a number instead."
如果尝试将 130.43 初始化为十进制
if let value = try! container.decode(Decimal.self, forKey: .d) {
//value.description is 130.43000000000002048
self.d = Decimal(string: value.description)
//making subtotal to be also 130.43000000000002048 and not 130.43
}
Run Code Online (Sandbox Code Playgroud)
解码时有什么方法可以使用这个构造函数吗?
NSDecimalNumber(string: "1.66")NSDecimalNumber(value: 166).dividing(by: 100)Decimal(166)/Decimal(100)Decimal(sign: .plus, exponent: -2, significand: 166)以下是我从外部服务收到的 JSON 的简化版本:
{
"priceAfterTax": 150.00, …Run Code Online (Sandbox Code Playgroud)