{"id":15038383,"url":"https://github.com/0111b/jsondecoder-keypath","last_synced_at":"2025-09-10T10:37:51.682Z","repository":{"id":56916512,"uuid":"106134583","full_name":"0111b/JSONDecoder-Keypath","owner":"0111b","description":"Add key path support to the JSONDecoder","archived":false,"fork":false,"pushed_at":"2017-10-08T19:57:38.000Z","size":16,"stargazers_count":20,"open_issues_count":0,"forks_count":4,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-08-20T02:26:00.383Z","etag":null,"topics":["cocoapods","codable","encodable","keypath","swift-4","swift-package-manager"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"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/0111b.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-10-07T22:26:00.000Z","updated_at":"2025-06-27T22:54:24.000Z","dependencies_parsed_at":"2022-08-21T03:50:40.487Z","dependency_job_id":null,"html_url":"https://github.com/0111b/JSONDecoder-Keypath","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/0111b/JSONDecoder-Keypath","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0111b%2FJSONDecoder-Keypath","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0111b%2FJSONDecoder-Keypath/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0111b%2FJSONDecoder-Keypath/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0111b%2FJSONDecoder-Keypath/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/0111b","download_url":"https://codeload.github.com/0111b/JSONDecoder-Keypath/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0111b%2FJSONDecoder-Keypath/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274447618,"owners_count":25287114,"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","status":"online","status_checked_at":"2025-09-10T02:00:12.551Z","response_time":83,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["cocoapods","codable","encodable","keypath","swift-4","swift-package-manager"],"created_at":"2024-09-24T20:38:16.399Z","updated_at":"2025-09-10T10:37:51.644Z","avatar_url":"https://github.com/0111b.png","language":"Swift","readme":"# JSONDecoder-Keypath\n\n[![CircleCI](https://img.shields.io/circleci/project/github/0111b/JSONDecoder-Keypath.svg)](https://circleci.com/gh/0111b/JSONDecoder-Keypath) [![Isues](https://img.shields.io/github/issues/0111b/JSONDecoder-Keypath.svg)](https://github.com/0111b/JSONDecoder-Keypath/issues) ![License](https://img.shields.io/badge/license-MIT-ff69b4.svg) ![Swift Package Manager](https://img.shields.io/badge/spm-supported-blue.svg) ![Cocoapods](https://img.shields.io/badge/cocoapods-supported-blue.svg)\n\nAdd nested key path support to the Foundation.JSONDecoder\n\n\u003c!-- TOC --\u003e\n\n- [Rationale](#rationale)\n- [Usage](#usage)\n- [Under the hood](#under-the-hood)\n- [Installation](#installation)\n    - [Swift Package Manager](#swift-package-manager)\n    - [Cocoapods](#cocoapods)\n- [Conclusion](#conclusion)\n- [Plans and improvements](#plans-and-improvements)\n\n\u003c!-- /TOC --\u003e\n\n### Rationale\n\nAt the time of writing, I found that most of the popular frameworks (mostly network wrappers) when dealing with keypath do some terrible things.\n\nSo, suppose we have a `Decodable` (`Codable`) object but in the API response we are getting it under some custom path.  Most of the solutions already have interface to extract object by keypath and also added `Codable` support. But the problem is that in almost all cases that I've seen implementation is next:\n1. Extract  `[String: Any]` from the `Data` with `JSONSerialization`\n2. Follow keypath in this dictionary\n3. Convert given object to `Data`\n4. Use `JSONDecoder` to parse object\n\nIt is obvious that the conversion of data back and forth is an extra waste of resources. In addition, on large amounts of data, this is highly not advisable.\n\nThis package eliminates first 3 steps.\n\n### Usage\n\nSay you have a `Item` model\n\n```Swift\nstruct Item: Codable {\n ...\n}\n```\n\nAnd we have a following JSON:\n\n```JSON\n{\n \"foo\" : \u003cactual object\u003e\n}\n```\n\nTo parse this you need to write:\n\n```Swift\nlet jsonData: Data = ...\nlet item = try decoder.decode(Item.self, from: jsonData, keyPath: \"foo\")\n```\n\nNested keypath are also supported:\n\n```Swift\nlet item = try decoder.decode(Item.self, from: jsonData, keyPath: \"foo.bar\")\n```\n\nKeypath separator can be configured:\n\n```Swift\nlet item = try decoder.decode(Item.self, from: jsonData, keyPath: \"foo/bar\", keyPathSeparator: \"/\")\n```\n\n### Under the hood\n\nPackage adds new method to the `JSONDecoder`\n\n```Swift\nfunc decode\u003cT\u003e(_ type: T.Type,\n                   from data: Data,\n                   keyPath: String,\n                   keyPathSeparator separator: String = \".\") throws -\u003e T where T : Decodable\n```\n\nIn this call `keypath` is stored in the `JSONDecoder.userInfo` and then standard `decode` method is called with private class `KeyPathWrapper\u003cT\u003e` as a type parameter. In the `KeyPathWrapper` constructor keypath data is fetched from the `userInfo` and decoder is traversed with this values. After that original type is decoded.\n\n### Installation\n\n#### Swift Package Manager\n\nAdd the line `.Package(url: \"https://github.com/0111b/JSONDecoder-Keypath.git\")` to your `Package.swift`\n\n#### Cocoapods\n\n```Ruby\n    pod 'JSONDecoder-Keypath'\n```\n\n### Conclusion\nMostly this is a naive implementation of the custom object encoding and took from me no more than a few hours. But it is showing that we must think how we are working with provided API's and not be lazy to look under the hood\n\n### Plans and improvements\n- [ ] Extend unit tests\n- [x] Add cocoapods spec \n- [ ] Add Carthage support\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F0111b%2Fjsondecoder-keypath","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F0111b%2Fjsondecoder-keypath","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F0111b%2Fjsondecoder-keypath/lists"}