{"id":13635069,"url":"https://github.com/JohnSundell/Wrap","last_synced_at":"2025-04-19T03:34:19.127Z","repository":{"id":62457267,"uuid":"47517218","full_name":"JohnSundell/Wrap","owner":"JohnSundell","description":"[DEPRECATED] The easy to use Swift JSON encoder","archived":true,"fork":false,"pushed_at":"2021-05-20T08:25:19.000Z","size":603,"stargazers_count":731,"open_issues_count":7,"forks_count":47,"subscribers_count":15,"default_branch":"master","last_synced_at":"2024-03-15T09:36:16.117Z","etag":null,"topics":["automatic","encoding","json","reflection","swift","xcode"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/JohnSundell.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-12-06T22:51:26.000Z","updated_at":"2024-03-02T00:52:10.000Z","dependencies_parsed_at":"2022-11-02T00:15:35.166Z","dependency_job_id":null,"html_url":"https://github.com/JohnSundell/Wrap","commit_stats":null,"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JohnSundell%2FWrap","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JohnSundell%2FWrap/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JohnSundell%2FWrap/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JohnSundell%2FWrap/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/JohnSundell","download_url":"https://codeload.github.com/JohnSundell/Wrap/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249600503,"owners_count":21297707,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["automatic","encoding","json","reflection","swift","xcode"],"created_at":"2024-08-02T00:00:40.319Z","updated_at":"2025-04-19T03:34:18.824Z","avatar_url":"https://github.com/JohnSundell.png","language":"Swift","readme":"⚠️ **DEPRECATED**\n\nWrap is deprecated in favor of Swift’s built-in `Codable` API and [the Codextended project](https://github.com/JohnSundell/Codextended). All current users are highly encouraged to migrate to `Codable` as soon as possible.\n\n---\n\n\u003cp align=\"center\"\u003e\n    \u003cimg src=\"logo.png\" width=\"300\" max-width=\"50%\" alt=\"Wrap\" /\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://github.com/johnsundell/unbox\"\u003eUnbox\u003c/a\u003e\n    |\n    \u003cb\u003eWrap\u003c/b\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://dashboard.buddybuild.com/apps/5936eda6f22b9400013db5cc/build/latest?branch=master\"\u003e\n        \u003cimg src=\"https://dashboard.buddybuild.com/api/statusImage?appID=5936eda6f22b9400013db5cc\u0026branch=master\u0026build=latest\" alt=\"BuddyBuild\" /\u003e\n    \u003c/a\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Swift-4.0-orange.svg\" /\u003e\n    \u003ca href=\"https://cocoapods.org/pods/Wrap\"\u003e\n        \u003cimg src=\"https://img.shields.io/cocoapods/v/Wrap.svg\" alt=\"CocoaPods\" /\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://github.com/Carthage/Carthage\"\u003e\n        \u003cimg src=\"https://img.shields.io/badge/carthage-compatible-4BC51D.svg?style=flat\" alt=\"Carthage\" /\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://twitter.com/johnsundell\"\u003e\n        \u003cimg src=\"https://img.shields.io/badge/contact-@johnsundell-blue.svg?style=flat\" alt=\"Twitter: @johnsundell\" /\u003e\n    \u003c/a\u003e\n\u003c/p\u003e\n\nWrap is an easy to use Swift JSON encoder. Don't spend hours writing JSON encoding code - just wrap it instead!\n\nUsing Wrap is as easy as calling `wrap()` on any instance of a `class` or `struct` that you wish to encode. It automatically encodes all of your type’s properties, including nested objects, collections, enums and more!\n\nIt also provides a suite of simple but powerful customization APIs that enables you to use it on any model setup with ease.\n\n## Basic example\n\nSay you have your usual-suspect `User` model:\n\n```swift\nstruct User {\n    let name: String\n    let age: Int\n}\n\nlet user = User(name: \"John\", age: 28)\n```\n\nUsing `wrap()` you can now encode a `User` instance with one command:\n\n```swift\nlet dictionary: [String : Any] = try wrap(user)\n```\n\nWhich will produce the following `Dictionary`:\n\n```json\n{\n    \"name\": \"John\",\n    \"age\": 28\n}\n```\n\n## Advanced example\n\nThe first was a pretty simple example, but Wrap can encode even the most complicated structures for you, with both optional, non-optional and custom type values, all without any extra code on your part. Let’s say we have the following model setup:\n\n```swift\nstruct SpaceShip {\n    let type: SpaceShipType\n    let weight: Double\n    let engine: Engine\n    let passengers: [Astronaut]\n    let launchLiveStreamURL: URL?\n    let lastPilot: Astronaut?\n}\n\nenum SpaceShipType: Int, WrappableEnum {\n    case apollo\n    case sputnik\n}\n\nstruct Engine {\n    let manufacturer: String\n    let fuelConsumption: Float\n}\n\nstruct Astronaut {\n    let name: String\n}\n```\n\nLet’s create an instance of `SpaceShip`:\n\n```swift\nlet ship = SpaceShip(\n    type: .apollo,\n    weight: 3999.72,\n    engine: Engine(\n        manufacturer: \"The Space Company\",\n        fuelConsumption: 17.2321\n    ),\n    passengers: [\n        Astronaut(name: \"Mike\"),\n        Astronaut(name: \"Amanda\")\n    ],\n    launchLiveStreamURL: URL(string: \"http://livestream.com\"),\n    lastPilot: nil\n)\n```\n\nAnd now let’s encode it with one call to `wrap()`:\n\n```swift\nlet dictionary: WrappedDictionary = try wrap(ship)\n```\n\nWhich will produce the following dictionary:\n\n```json\n{\n    \"type\": 0,\n    \"weight\": 3999.72,\n    \"engine\": {\n        \"manufacturer\": \"The Space Company\",\n        \"fuelConsumption\": 17.2321\n    },\n    \"passengers\": [\n        {\"name\": \"Mike\"},\n        {\"name\": \"Amanda\"}\n    ],\n    \"launchLiveStreamURL\": \"http://livestream.com\"\n}\n```\n\nAs you can see, Wrap automatically encoded the `URL` property to its `absoluteString`, and ignored any properties that were `nil` (reducing the size of the produced JSON).\n\n## Customization\n\nWhile automation is awesome, customization is just as important. Thankfully, Wrap provides several override points that enables you to easily tweak its default behavior.\n\n### Customizing keys\n\nPer default Wrap uses the property names of a type as its encoding keys, but sometimes this is not what you’re looking for. You can choose to override any or all of a type’s encoding keys by making it conform to `WrapCustomizable` and implementing `keyForWrapping(propertyNamed:)`, like this:\n\n```swift\nstruct Book: WrapCustomizable {\n    let title: String\n    let authorName: String\n\n    func keyForWrapping(propertyNamed propertyName: String) -\u003e String? {\n        if propertyName == \"authorName\" {\n            return \"author_name\"\n        }\n\n        return propertyName\n    }\n}\n```\n\nYou can also use the `keyForWrapping(propertyNamed:)` API to skip a property entirely, by returning nil from this method for it.\n\n### Custom key types\n\nYou might have nested dictionaries that are not keyed on `Strings`, and for those Wrap provides the `WrappableKey` protocol. This enables you to easily convert any type into a string that can be used as a JSON key.\n\n### Encoding keys as snake_case\n\nIf you want the dictionary that Wrap produces to have snake_cased keys rather than the default (which is matching the names of the properties that were encoded), you can easily do so by conforming to `WrapCustomizable` and returning `.convertToSnakeCase` from the `wrapKeyStyle` property. Doing that will, for example, convert the property name `myProperty` into the key `my_property`.\n\n### Customized wrapping\n\nFor some nested types, you might want to handle the wrapping yourself. This may be especially true for any custom collections, or types that have a completely different representation when encoded. To do that, make a type conform to `WrapCustomizable` and implement `wrap(context:dateFormatter:)`, like this:\n\n```swift\nstruct Library: WrapCustomizable {\n    private let booksByID: [String : Book]\n\n    func wrap(context: Any?, dateFormatter: DateFormatter?) -\u003e Any? {\n        return Wrapper(context: context, dateFormatter: dateFormatter).wrap(self.booksByID)\n    }\n}\n```\n\n## Enum support\n\nWrap also makes it super easy to encode any `enum` values that your types are using. If an `enum` is based on a raw type (such as `String` or `Int`), all you have to do is to declare conformance to `WrappableEnum`, and the rest is taken care of for you.\n\nNon-raw type `enum` values are also automatically encoded. The default behavior encodes any values that don’t have associated values as their string representation, and those that do have associated values as a dictionary (with the string representation as the key), like this:\n\n```swift\nenum Profession {\n    case developer(favoriteLanguageName: String)\n    case lawyer\n}\n\nstruct Person {\n    let profession = Profession.developer(favoriteLanguageName: \"Swift\")\n    let hobbyProfession = Profession.lawyer\n}\n```\n\nEncodes into:\n\n```json\n{\n    \"profession\": {\n        \"developer\": \"Swift\"\n    },\n    \"hobbyProfession\": \"lawyer\"\n}\n```\n\n## Contextual objects\n\nTo be able to easily encode any dependencies that you might want to use during the encoding process, Wrap provides the ability to supply a contextual object when initiating the wrapping process (by calling `wrap(object, context: myContext`).\n\nA context can be of `Any` type and is accessible in all `WrapCustomizable` wrapping methods. Here is an example, where we send in a prefix to add to a `Book`’s `title`:\n\n```swift\nstruct Book: WrapCustomizable {\n    let title: String\n\n    func wrap(context: Any?, dateFormatter: DateFormatter?) -\u003e Any? {\n        guard let prefix = context as? String else {\n            return nil\n        }\n\n        return [\n            \"title\" : prefix + self.title\n        ]\n    }\n}\n```\n\n## String serialization\n\n```swift\nlet data = try wrap(object) as Data\nlet string = String(data: data, encoding: .utf8)\n```\n\n## Compatibility\n\nWrap supports the following platforms:\n\n- 📱 iOS 8+\n- 🖥 macOS 10.9+\n- ⌚️ watchOS 2+\n- 📺 tvOS 9+\n- 🐧 Linux\n\n## Usage\n\nWrap can be easily used in either a Swift script, command line tool or in an app for iOS, macOS, watchOS, tvOS or Linux.\n\n### In an application\n\nEither\n\n- Drag the file `Wrap.swift` into your application's Xcode project.\n\nor\n\n- Use [CocoaPods](cocoapods.org), [Carthage](https://github.com/Carthage/Carthage) or the [Swift Package Manager](https://github.com/apple/swift-package-manager) to include Wrap as a dependency in your project.\n\n### In a script\n\n- Install [Marathon](https://github.com/johnsundell/marathon).\n- Add Wrap using `$ marathon add https://github.com/JohnSundell/Wrap.git`.\n- Run your script using `$ marathon run \u003cpath-to-your-script\u003e`.\n\n### In a command line tool\n\n- Drag the file `Wrap.swift` into your command line tool's Xcode project.\n\n### Hope you enjoy wrapping your objects!\n\nFor more updates on Wrap, and my other open source projects, follow me on Twitter: [@johnsundell](http://www.twitter.com/johnsundell)\n\nAlso make sure to check out [Unbox](http://github.com/johnsundell/unbox) that let’s you easily **decode** JSON.\n","funding_links":[],"categories":["JSON Parse","HarmonyOS","Parsing"],"sub_categories":["Windows Manager"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FJohnSundell%2FWrap","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FJohnSundell%2FWrap","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FJohnSundell%2FWrap/lists"}