Swift结构:为单个属性处理多种类型

我正在使用Swift 4并尝试解析一些JSON数据,这些数据显然在某些情况下对于同一键可能具有不同的类型值,例如:

{

"type": 0.0

}

{

"type": "12.44591406"

}

我实际上坚持定义我的名字,struct因为我不知道如何处理这种情况,因为

struct ItemRaw: Codable {

let parentType: String

enum CodingKeys: String, CodingKey {

case parentType = "type"

}

}

抛出"Expected to decode String but found a number instead.",自然,

struct ItemRaw: Codable {

let parentType: Float

enum CodingKeys: String, CodingKey {

case parentType = "type"

}

}

相应地抛出"Expected to decode Float but found a string/data instead."

定义我时如何处理这种(和类似的)情况struct

回答:

尝试对Reddit列表JSON响应上的“已编辑”字段进行解码/编码时遇到了相同的问题。我创建了一个结构,该结构表示给定键可能存在的动态类型。键可以是布尔值或整数。

{ "edited": false }

{ "edited": 123456 }

如果只需要能够解码,则只需实现init(from :)。如果您需要同时使用两种方法,则需要实现encode(to :)函数。

struct Edited: Codable {

let isEdited: Bool

let editedTime: Int

// Where we determine what type the value is

init(from decoder: Decoder) throws {

let container = try decoder.singleValueContainer()

// Check for a boolean

do {

isEdited = try container.decode(Bool.self)

editedTime = 0

} catch {

// Check for an integer

editedTime = try container.decode(Int.self)

isEdited = true

}

}

// We need to go back to a dynamic type, so based on the data we have stored, encode to the proper type

func encode(to encoder: Encoder) throws {

var container = encoder.singleValueContainer()

try isEdited ? container.encode(editedTime) : container.encode(false)

}

}

在我的Codable类中,然后使用我的结构。

struct Listing: Codable {

let edited: Edited

}

我建议在解码时使用CodingKey协议和一个枚举来存储所有属性。当您创建符合Codable的内容时,编译器将为您创建一个私有枚举CodingKeys。这使您可以根据JSON

Object属性键决定要做什么。

仅举例来说,这就是我正在解码的JSON:

{"type": "1.234"}

{"type": 1.234}

如果您只想将double值从字符串转换为Double,则只需解码字符串,然后从中创建一个double。(这是Itai

Ferber所做的,然后您还必须使用trycoder.decode(type:forKey :)对所有属性进行解码)

struct JSONObjectCasted: Codable {

let type: Double?

init(from decoder: Decoder) throws {

// Decode all fields and store them

let container = try decoder.container(keyedBy: CodingKeys.self) // The compiler creates coding keys for each property, so as long as the keys are the same as the property names, we don't need to define our own enum.

// First check for a Double

do {

type = try container.decode(Double.self, forKey: .type)

} catch {

// The check for a String and then cast it, this will throw if decoding fails

if let typeValue = Double(try container.decode(String.self, forKey: .type)) {

type = typeValue

} else {

// You may want to throw here if you don't want to default the value(in the case that it you can't have an optional).

type = nil

}

}

// Perform other decoding for other properties.

}

}

如果需要将类型和值一起存储,则可以使用符合Codable的枚举而不是struct。然后,您可以仅使用具有JSONObjectCustomEnum的“

type”属性的switch语句,并根据大小写执行操作。

struct JSONObjectCustomEnum: Codable {

let type: DynamicJSONProperty

}

// Where I can represent all the types that the JSON property can be.

enum DynamicJSONProperty: Codable {

case double(Double)

case string(String)

init(from decoder: Decoder) throws {

let container = try decoder.singleValueContainer()

// Decode the double

do {

let doubleVal = try container.decode(Double.self)

self = .double(doubleVal)

} catch DecodingError.typeMismatch {

// Decode the string

let stringVal = try container.decode(String.self)

self = .string(stringVal)

}

}

func encode(to encoder: Encoder) throws {

var container = encoder.singleValueContainer()

switch self {

case .double(let value):

try container.encode(value)

case .string(let value):

try container.encode(value)

}

}

}

以上是 Swift结构:为单个属性处理多种类型 的全部内容, 来源链接: utcz.com/qa/425059.html

回到顶部