GithubHelp home page GithubHelp logo

qlcdfork / codablewrapper Goto Github PK

View Code? Open in Web Editor NEW

This project forked from winddpan/codablewrapper

0.0 0.0 0.0 393 KB

@Codec("encoder", "decoder") var cool: Bool = true

License: MIT License

Swift 100.00%

codablewrapper's Introduction

Requirements

Xcode Minimun Deployments Version
Xcode15 >= iOS13 / macOS11 1.0
< Xcode15 < iOS13 / macOS11 0.3.3

About

The project objective is to enhance the usage experience of the Codable protocol using the macro provided by Swift 5.9 and to address the shortcomings of various official versions.

Feature

  • Default value
  • Basic type automatic convertible, between String Bool Number etc.
  • Custom multiple CodingKey
  • Nested Dictionary CodingKey
  • Automatic compatibility between camel case and snake case
  • Convenience Codable subclass
  • Transformer

Installation

Cocoapods Beta test

pod 'CodableWrapper', :git => 'https://github.com/winddpan/CodableWrapper.git', :branch => '1.1.0'

Swift Package Manager

https://github.com/winddpan/CodableWrapper

Example

@Codable
struct BasicModel {
    var defaultVal: String = "hello world"
    var defaultVal2: String = Bool.random() ? "hello world" : ""
    let strict: String
    let noStrict: String?
    let autoConvert: Int?

    @CodingKey("hello")
    var hi: String = "there"

    @CodingNestedKey("nested.hi")
    @CodingTransformer(StringPrefixTransform("HELLO -> "))
    var codingKeySupport: String

    @CodingNestedKey("nested.b")
    var nestedB: String

    var testGetter: String {
        nestedB
    }
}

final class CodableWrapperTests: XCTestCase {
    func testBasicUsage() throws {
        let jsonStr = """
        {
            "strict": "value of strict",
            "autoConvert": "998",
            "nested": {
                "hi": "nested there",
                "b": "b value"
            }
        }
        """

        let model = try JSONDecoder().decode(BasicModel.self, from: jsonStr.data(using: .utf8)!)
        XCTAssertEqual(model.defaultVal, "hello world")
        XCTAssertEqual(model.strict, "value of strict")
        XCTAssertEqual(model.noStrict, nil)
        XCTAssertEqual(model.autoConvert, 998)
        XCTAssertEqual(model.hi, "there")
        XCTAssertEqual(model.codingKeySupport, "HELLO -> nested there")
        XCTAssertEqual(model.nestedB, "b value")

        let encoded = try JSONEncoder().encode(model)
        let dict = try JSONSerialization.jsonObject(with: encoded) as! [String: Any]
        XCTAssertEqual(model.defaultVal, dict["defaultVal"] as! String)
        XCTAssertEqual(model.strict, dict["strict"] as! String)
        XCTAssertNil(dict["noStrict"])
        XCTAssertEqual(model.autoConvert, dict["autoConvert"] as? Int)
        XCTAssertEqual(model.hi, dict["hello"] as! String)
        XCTAssertEqual("nested there", (dict["nested"] as! [String: Any])["hi"] as! String)
        XCTAssertEqual(model.nestedB, (dict["nested"] as! [String: Any])["b"] as! String)
    }
}

Macro usage

@Codable

  • Auto conformance Codable protocol if not explicitly declared

    // both below works well
    
    @Codable
    struct BasicModel {}
    
    @Codable
    struct BasicModel: Codable {}
  • Default value

    @Codable
    struct TestModel {
        let name: String
        var balance: Double = 0
    }
    
    // { "name": "jhon" }
  • Basic type automatic convertible, between String Bool Number etc.

    @Codable
    struct TestModel {
        let autoConvert: Int?
    }
    
    // { "autoConvert": "998" }
  • Automatic compatibility between camel case and snake case

    @Codable
    struct TestModel {
        var userName: String = ""
    }
    
    // { "user_name": "jhon" }
  • Member Wise Init

    @Codable
    public struct TestModel {
        public var userName: String = ""
    
        // Automatic generated
        public init(userName: String = "") {
            self.userName = userName
        }
    }

@CodingKey

  • Custom CodingKeys

    @Codable
    struct TestModel {
        @CodingKey("u1", "u2", "u9")
        var userName: String = ""
    }
    
    // { "u9": "jhon" }

@CodingNestedKey

  • Custom CodingKeys in nested dictionary

    @Codable
    struct TestModel {
        @CodingNestedKey("data.u1", "data.u2", "data.u9")
        var userName: String = ""
    }
    
    // { "data": {"u9": "jhon"} }

@CodableSubclass

  • Automatic generate Codable class's subclass init(from:) and encode(to:) super calls

    @Codable
    class BaseModel {
        let userName: String
    }
    
    @CodableSubclass
    class SubModel: BaseModel {
        let age: Int
    }
    
    // {"user_name": "jhon", "age": 22}

@CodingTransformer

  • Transformer between in Codable / NonCodable model

    struct DateWrapper {
        let timestamp: TimeInterval
    
        var date: Date {
            Date(timeIntervalSince1970: timestamp)
        }
    
        init(timestamp: TimeInterval) {
            self.timestamp = timestamp
        }
    
        static var transformer = TransformOf<DateWrapper, TimeInterval>(fromJSON: { DateWrapper(timestamp: $0 ?? 0) }, toJSON: { $0.timestamp })
    }
    
    @Codable
    struct DateModel {
        @CodingTransformer(DateWrapper.transformer)
        var time: DateWrapper? = DateWrapper(timestamp: 0)
        
        @CodingTransformer(DateWrapper.transformer)
        var time1: DateWrapper = DateWrapper(timestamp: 0)
        
        @CodingTransformer(DateWrapper.transformer)
        var time2: DateWrapper?
    }
    
    class TransformTest: XCTestCase {
        func testDateModel() throws {
            let json = """
            {"time": 12345}
            """
    
            let model = try JSONDecoder().decode(DateModel.self, from: json.data(using: .utf8)!)
            XCTAssertEqual(model.time?.timestamp, 12345)
            XCTAssertEqual(model.time?.date.description, "1970-01-01 03:25:45 +0000")
    
            let encode = try JSONEncoder().encode(model)
            let jsonObject = try JSONSerialization.jsonObject(with: encode, options: []) as! [String: Any]
            XCTAssertEqual(jsonObject["time"] as! TimeInterval, 12345)
        }
    }

codablewrapper's People

Contributors

winddpan avatar scyano avatar rakuyomo avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.