Closed Bastosss77 closed 5 years ago
Yeah, decoding directly to Any
isn't something we support, and we really couldn't even if we wanted to. In order for decoding to work properly you really need to know the type you're trying to decode to. To make matters worse, you're not going to be able to differentiate between Float
and Int
values because by the time we get them, they are represented as NSNumber
instances. This might change in the future if we ditch Foundation, but for now this is where we are. It's not a great practice to let different types exist under the same JSON key. If you happen to have the ability to change the JSON response I'd definitely recommend standardizing it to return consistent types.
That being said, if I didn't have control over the JSON, I'd probably split out the individual possibilities and then use <|>
to set up a kind of precedence chain for them inside the decoder itself:
extension DocumentRuleWSModel: Argo.Decodable {
static func decode(_ json: JSON) -> Decoded<DocumentRuleWSModel> {
let stringValue: Decoded<String> = json <| "value"
let floatValue: Decoded<Float> = json <| "value" // Choosing Float here to reduce the risk of losing precision.
return curry(DocumentRuleWSModel.init)
<^> json <| "key"
<*> json <| "label"
<*> .optional(stringValue <|> floatValue)
}
}
Note that the order here is important. <|>
will select the first .success
value it sees.
Another option might be to wrap your end type in a custom enum
type that specifies the types you expect. Something like:
enum DocumentRuleValue {
case string(String)
case float(Float)
}
extension DocumentRuleValue: Argo.Decodable {
static func decode(_ json: JSON) -> Decoded<DocumentRuleValue> {
switch json {
case let .string(str): return .string(str)
case let .number(num): return .float(num.floatValue)
default: return .typeMismatch(expected: "DocumentRuleValue", actual: json)
}
}
}
// then
struct DocumentRuleWSModel: BaseWSModel {
let key: String
let label: String
let value: DocumentRuleValue?
}
extension DocumentRuleWSModel: Argo.Decodable {
static func decode(_ json: JSON) -> Decoded<DocumentRuleWSModel> {
return curry(DocumentRuleWSModel.init)
<^> json <| "key"
<*> json <| "label"
<*> json <|? "value"
}
}
I'm going to go ahead and close this due to inactivity but please feel free to reopen if you have any more questions.
Hi guys,
I have a JSON with a field could be String, Integer or Float and I don't know how to decode it.
This is a part of my models :
I tried to match it with
Any
but it doesn't work and I have no idea how to handle this problemI'm using Argo 4.1