All Projects → winddpan → CodableWrapper

winddpan / CodableWrapper

Licence: MIT license
@codec("encoder", "decoder") var cool: Bool = true

Programming Languages

swift
15916 projects
ruby
36898 projects - #4 most used programming language

Projects that are alternatives of or similar to CodableWrapper

Fasteasymapping
A tool for fast serializing & deserializing of JSON
Stars: ✭ 556 (+288.81%)
Mutual labels:  serialization, mapping, deserialization
Handyjson
A handy swift json-object serialization/deserialization library
Stars: ✭ 3,913 (+2636.36%)
Mutual labels:  serialization, mapping, deserialization
Mappable
flexible JSON to Model converter, specially optimized for immutable properties
Stars: ✭ 27 (-81.12%)
Mutual labels:  mapping, deserialization
sqlathanor
Serialization / De-serialization support for the SQLAlchemy Declarative ORM
Stars: ✭ 105 (-26.57%)
Mutual labels:  serialization, deserialization
bytes
Work with bytes and implement network protocols
Stars: ✭ 77 (-46.15%)
Mutual labels:  serialization, deserialization
Jsonapi Rails
Rails gem for fast jsonapi-compliant APIs.
Stars: ✭ 242 (+69.23%)
Mutual labels:  serialization, deserialization
avro-serde-php
Avro Serialisation/Deserialisation (SerDe) library for PHP 7.3+ & 8.0 with a Symfony Serializer integration
Stars: ✭ 43 (-69.93%)
Mutual labels:  serialization, deserialization
har-rs
A HTTP Archive format (HAR) serialization & deserialization library, written in Rust.
Stars: ✭ 25 (-82.52%)
Mutual labels:  serialization, deserialization
Dart Json Mapper
Serialize / Deserialize Dart Objects to / from JSON
Stars: ✭ 206 (+44.06%)
Mutual labels:  serialization, deserialization
serde
🚝 (unmaintained) A framework for defining, serializing, deserializing, and validating data structures
Stars: ✭ 49 (-65.73%)
Mutual labels:  serialization, deserialization
sexp-grammar
Invertible parsing for S-expressions
Stars: ✭ 28 (-80.42%)
Mutual labels:  serialization, deserialization
cattrs
Complex custom class converters for attrs.
Stars: ✭ 565 (+295.1%)
Mutual labels:  serialization, deserialization
Jsonapi Rb
Efficiently produce and consume JSON API documents.
Stars: ✭ 219 (+53.15%)
Mutual labels:  serialization, deserialization
Schematics
Project documentation: https://schematics.readthedocs.io/en/latest/
Stars: ✭ 2,461 (+1620.98%)
Mutual labels:  serialization, deserialization
nason
🗜 Ultra tiny serializer / encoder with plugin-support. Useful to build binary files containing images, strings, numbers and more!
Stars: ✭ 30 (-79.02%)
Mutual labels:  serialization, deserialization
Mashumaro
Fast and well tested serialization framework on top of dataclasses
Stars: ✭ 208 (+45.45%)
Mutual labels:  serialization, deserialization
marshmallow-validators
Use 3rd-party validators (e.g. from WTForms and colander) with marshmallow
Stars: ✭ 24 (-83.22%)
Mutual labels:  serialization, deserialization
avrow
Avrow is a pure Rust implementation of the avro specification https://avro.apache.org/docs/current/spec.html with Serde support.
Stars: ✭ 27 (-81.12%)
Mutual labels:  serialization, deserialization
Aspjson
A fast classic ASP JSON parser and encoder for easy JSON manipulation to work with the new JavaScript MV* libraries and frameworks.
Stars: ✭ 165 (+15.38%)
Mutual labels:  serialization, deserialization
Marshmallow Jsonapi
JSON API 1.0 (https://jsonapi.org/) formatting with marshmallow
Stars: ✭ 203 (+41.96%)
Mutual labels:  serialization, deserialization

CodableWrapper

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

  1. About
  2. Feature
  3. Installation
  4. Example
  5. How it works
  6. Usage

中文说明

About

  • This project is use PropertyWrapper to improve your Codable use experience.
  • Simply based on JSONEncoder JSONDecoder.
  • Powerful and simplifily API than BetterCodable or CodableWrappers.

Feature

  • Default value supported
  • Basic type convertible, between String Bool Number
  • Custom key support
  • Fix parsing failure due to missing fields from server
  • Fix parsing failure due to mismatch Enum raw value
  • Custom transform

Installation

Cocoapods

pod 'CodableWrapper'

Swift Package Manager

https://github.com/winddpan/CodableWrapper

Example

enum Animal: String, Codable {
    case dog
    case cat
    case fish
}

struct ExampleModel: Codable {
    @Codec("aString")
    var stringVal: String = "scyano"

    @Codec("aInt")
    var intVal: Int = 123456

    @Codec var defaultArray: [Double] = [1.998, 2.998, 3.998]

    @Codec var bool: Bool = false

    @Codec var unImpl: String?
    
    @Codec var animal: Animal = .dog
}

let json = #"{"aString": "pan", "aInt": "233", "bool": "1", "animal": "cat"}"#

let model = try JSONDecoder().decode(ExampleModel.self, from: json.data(using: .utf8)!)
XCTAssertEqual(model.stringVal, "pan")
XCTAssertEqual(model.intVal, 233)
XCTAssertEqual(model.defaultArray, [1.998, 2.998, 3.998])
XCTAssertEqual(model.bool, true)
XCTAssertEqual(model.unImpl, nil)
XCTAssertEqual(model.animal, .cat)

For more examples, please check the unit tests or Playground

How it works

struct DataModel: Codable {
    @Codec var stringVal: String = "OK"
}

/* pseudocode from Swift open source lib: Codable.Swift -> */
struct DataModel: Codable {
    private var _stringVal = Codec<String>(defaultValue: "OK")

    var stringVal: String {
        get {
            return _stringVal.wrappedValue
        }
        set {
            _stringVal.wrappedValue = newValue
        }
    }

    enum CodingKeys: CodingKey {
        case stringVal
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)

        /* decode `newStringVal` */
        /* remember `newStringVal`: Thread.current.lastCodableWrapper = wrapper */
        /*
         extension KeyedDecodingContainer {
            func decode<Value>(_ type: Codec<Value>.Type, forKey key: Key) throws -> Codec<Value> {
                ...
                let wrapper = Codec<Value>(unsafed: ())
                Thread.current.lastCodableWrapper = wrapper
                ...
            }
         }
         */
        let newStringVal = try container.decode(Codec<String>.self, forKey: CodingKeys.stringVal)

        /* old `_stringVal` deinit */
        /* old `_stringVal` invokeAfterInjection called: transform old `_stringVal` Configs to `newStringVal` */
        /* 
         deinit {
             if !unsafeCreated, let construct = construct, let lastWrapper = Thread.current.lastCodableWrapper as? Codec<Value> {
                 lastWrapper.invokeAfterInjection(with: construct)
                 Thread.current.lastCodableWrapper = nil
             }
         }
        */
        self._stringVal = newStringVal
    }
}

Usage

DefaultValue

DefaultValue should implement Codable protocol

struct ExampleModel: Codable {
    @Codec var bool: Bool = false
}

let json = #"{"bool":"wrong value"}"#

let model = try JSONDecoder().decode(ExampleModel.self, from: json.data(using: .utf8)!)
XCTAssertEqual(model.bool, false)

Auto snake camel convert

struct ExampleModel: Codable {
    @Codec var snake_string: String = ""
    @Codec var camelString: String = ""
}

let json = #"{"snakeString":"snake", "camel_string": "camel"}"#

let model = try JSONDecoder().decode(ExampleModel.self, from: json.data(using: .utf8)!)
XCTAssertEqual(model.snake_string, "snake")
XCTAssertEqual(model.camelString, "camel")

CodingKeys

Decoding: try each CodingKey until succeed Encoding: use first CodingKey as Dictionary key

struct ExampleModel: Codable {
    @Codec("int_Val", "intVal")
    var intVal: Int = 123456

    @Codec("intOptional", "int_optional")
    var intOptional: Int?
}

let json = #"{"int_Val": "233", "int_optional": 234}"#

let model = try JSONDecoder().decode(ExampleModel.self, from: json.data(using: .utf8)!)
XCTAssertEqual(model.intVal, 233)
XCTAssertEqual(model.intOptional, 234)

let data = try JSONEncoder().encode(model)
let jsonObject = try JSONSerialization.jsonObject(with: data, options: []) as! [String: Any]
XCTAssertEqual(jsonObject["int_Val"] as? Int, 233)
XCTAssertEqual(jsonObject["intOptional"] as? Int, 234)

Basic type bridging

struct ExampleModel: Codable {
    @Codec var int: Int?
    @Codec var string: String?
    @Codec var bool: Bool?
}

let json = #"{"int": "1", "string": 2, "bool": "true"}"#

let model = try JSONDecoder().decode(ExampleModel.self, from: json.data(using: .utf8)!)
XCTAssertEqual(model.int, 1)
XCTAssertEqual(model.string, "2")
XCTAssertEqual(model.bool, true)

Transformer

struct User: Codable {
    @Codec(transformer: SecondDateTransform())
    var registerDate: Date?
}       
let date = Date()
let json = #"{"sencondsDate": \(date.timeIntervalSince1970)}"#

let user = try JSONDecoder().decode(User.self, from: json.data(using: .utf8)!)
XCTAssertEqual(model.sencondsDate?.timeIntervalSince1970, date.timeIntervalSince1970)

It also support custom transformer, your CustomTransformer only need to comfirm to TransfromType

License

Distributed under the MIT License. See LICENSE for more information.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].