0

How would you write the decoding code for the following JSON:

{
   "identifier": "1",
   "issuer": "visa",
   "pattern": [5, [7, 9]]

}

To map it into the following model:

struct Card: Decodable {
    let identifier: String
    let issuer: String
    let pattern: [CardPattern]
}

enum CardPattern: Decodable {
    case prefix(Int)
    case range(start: Int, end: Int)
}

Notice how the pattern attribute in the json is a collection of two possible values:

  • Int indicating we should map into a CardPattern.prefix case
  • [Int] containing two values, indicating we should map into a CardPattern.range case (first value is start, second value is end)

1 Answer 1

1

Read about the singleValueContainer it should solve your problem. Here is a working snippet with testing...

enum CardPattern: Codable {
    case prefix(Int)
    case range(start: Int, end: Int)
    
    init(from decoder: Decoder) throws {
        let singleContainer = try decoder.singleValueContainer()
        do {
            let prefix = try singleContainer.decode(Int.self)
            self = .prefix(prefix)
            return
        } catch {
            print("Not a prefix")
        }
        
        do {
            let range = try singleContainer.decode([Int].self)
            self = .range(start: range[0], end: range[1])
            return
        } catch {
            print("Not a range")
        }
        throw NSError(domain: "Unknown type", code: -1)
    }
    
    func encode(to encoder: Encoder) throws {
        var singleContainer = encoder.singleValueContainer()
        switch self {
        case .prefix(let value):
            try singleContainer.encode(value)
        case .range(start: let start, end: let end):
            let range: [Int] = [start, end]
            try singleContainer.encode(range)
        }
    }
    
}


let data = [CardPattern.prefix(10), CardPattern.range(start: 2, end: 9)]
var encodedData: Data = Data()
do {
    encodedData = try JSONEncoder().encode(data)
    print(encodedData)
} catch {
    print("encode")
    print(error)
}
do {
    let decoded = try JSONDecoder().decode([CardPattern].self, from: encodedData)
    print(decoded)
} catch {
    print("decode")
    print(error)
}

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.