Skip to content

Instantly share code, notes, and snippets.

@popeyelau
Last active March 19, 2020 05:23
Show Gist options
  • Save popeyelau/95c52177f5ae7c701d36f10e98f7ff35 to your computer and use it in GitHub Desktop.
Save popeyelau/95c52177f5ae7c701d36f10e98f7ff35 to your computer and use it in GitHub Desktop.
HandyJSON & Decodable Custom Mapping|-|{"files":{"HandyJSON.md":{"env":"plain"}},"tag":"Gists"}
  {
    "rabbets": ["0.100-0.300", "0.301-0.500"]
  }
class SomeObject: HandyJSON {
    
    class Rabbet: HandyJSON {
        
        var begin: String?
        var end: String?
        
        required init() {}
        
        init(begin: String, end: String) {
            self.begin = begin
            self.end = end
        }
    }
    
    var rabbets: [Rabbet]?
    
    required init() {}
    
    public func mapping(mapper: HelpingMapper) {
        mapper <<<
            rabbets <-- ("rabbets", TransformOf<[Rabbet], [String]>(fromJSON: { (raw) -> [Rabbet]? in
                return raw?.compactMap { item -> Rabbet? in
                    let splited = item.split(separator: "-")
                    guard splited.count == 2 else { return nil }
                    return Rabbet(begin: String(splited[0]), end: String(splited[1]))
                }
            } , toJSON: { rabbets -> [String]? in
                return rabbets?.compactMap { item -> String? in
                    guard let begin = item.begin, let end = item.end else { return nil }
                    return "\(begin)-\(end)"
                }
            }))
    }
    
    required init(from decoder: Decoder) throws {
        let contaier = try decoder.container(keyedBy: CodingKeys.self)
        var unkeyed = try contaier.nestedUnkeyedContainer(forKey: .rabbets)
        var arr: [Rabbet] = []
        while !unkeyed.isAtEnd {
            let item = try unkeyed.decode(String.self)
            let splited = item.split(separator: "-")
            if splited.count == 2 {
                arr.append(Rabbet(begin: String(splited[0]), end: String(splited[1])))
            }
        }
        self.rabbets = arr
    }
}


extension SomeObject: Decodable{
    enum CodingKeys: String, CodingKey {
        case rabbets
    }

}
let json = """
{
    "rabbets": ["0.100-0.300", "0.301-0.500"]
}
"""
if let type = SomeObject.deserialize(from: json), let result = type.toJSONString(prettyPrint: true) {
    print(result)
}

let decoder = JSONDecoder()
let obj = try? decoder.decode(SomeObject.self, from: json.data(using: .utf8)!)
@popeyelau
Copy link
Author

import Foundation

var json = """
{
    "rabbets": ["0.100-0.300", "0.301-0.500"]
}
"""

struct SomeObject: Codable {
    
    var rabbets: [Rabbet]?
    
    /* decode in super class
    enum CodingKeys: String, CodingKey {
        case rabbets
    }

    required init(from decoder: Decoder) throws {
        let contaier = try decoder.container(keyedBy: CodingKeys.self)
        var unkeyed = try contaier.nestedUnkeyedContainer(forKey: .rabbets)
        var arr: [Rabbet] = []
        while !unkeyed.isAtEnd {
            let item = try unkeyed.decode(String.self)
            let splited = item.split(separator: "-")
            if splited.count == 2 {
                arr.append(Rabbet(begin: String(splited[0]), end: String(splited[1])))
            }
        }
        self.rabbets = arr
    }*/
}


struct Rabbet: Codable {
    var begin: String?
    var end: String?
    
    
    init(begin: String, end: String) {
        self.begin = begin
        self.end = end
    }
    
    enum CodingKeys: String, CodingKey {
        case begin
        case end
    }
    
    // decode self with a singleValueContainer
    // "0.100-0.300" -> {begin: 0.100, end: 0.300}
    public init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        let item = try container.decode(String.self)
        let splited = item.split(separator: "-")
        if splited.count == 2 {
            self.begin = String(splited[0])
            self.end = String(splited[1])
        }
    }
    
    // {begin: 0.100, end: 0.300} -> "0.100-0.300"
    public func encode(to encoder: Encoder) throws {
        var container = encoder.singleValueContainer()
        if let begin = begin, let end = end  {
            try container.encode("\(begin)-\(end)")
        }
    }
}

let decoder = JSONDecoder()
let decodeData = json.data(using: .utf8)!
let obj = try! decoder.decode(SomeObject.self, from: decodeData)
obj.rabbets


let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
let encodeData = try! encoder.encode(obj)
if let json = String(bytes: encodeData, encoding: .utf8) {
    print(json)
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment