{"id":20497420,"url":"https://github.com/mczachurski/swiftbenchmarkjson","last_synced_at":"2025-04-13T18:40:20.196Z","repository":{"id":90492539,"uuid":"130454618","full_name":"mczachurski/SwiftBenchmarkJSON","owner":"mczachurski","description":"Repository for Swift frameworks JSON benchmarks","archived":false,"fork":false,"pushed_at":"2019-03-14T18:34:47.000Z","size":1238,"stargazers_count":15,"open_issues_count":0,"forks_count":3,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-06T07:38:49.672Z","etag":null,"topics":["benchmark","json","swift"],"latest_commit_sha":null,"homepage":null,"language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mczachurski.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-04-21T08:24:46.000Z","updated_at":"2024-02-27T15:26:33.000Z","dependencies_parsed_at":null,"dependency_job_id":"770aaaa8-84c5-4858-85cc-3e96d1ce7e93","html_url":"https://github.com/mczachurski/SwiftBenchmarkJSON","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mczachurski%2FSwiftBenchmarkJSON","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mczachurski%2FSwiftBenchmarkJSON/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mczachurski%2FSwiftBenchmarkJSON/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mczachurski%2FSwiftBenchmarkJSON/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mczachurski","download_url":"https://codeload.github.com/mczachurski/SwiftBenchmarkJSON/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248764162,"owners_count":21158035,"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":["benchmark","json","swift"],"created_at":"2024-11-15T18:11:01.051Z","updated_at":"2025-04-13T18:40:20.181Z","avatar_url":"https://github.com/mczachurski.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Swift JSON Benchmarks\n\nBenchmark results for different Swift frameworks which work on JSON (encoding/decoding). For reference there is also a benchmark of .NET Core framework (Newtonsoft.JSON), however it's not included in ranks.\n\nAll benchmark was performed on my computer:\n\n - Device: MacBook Pro (13-inch, 2016, Two Thunderbolt 3 ports)\n - Processor: 2 GHz Intel Core i5\n - Memory: 16 GB 1867 MHz LPDDR3\n - Graphics: Intel Iris Graphics 540 1536  MB\n\nSwift version:\n\n```bash\nApple Swift version 4.2.1 (swiftlang-1000.11.42 clang-1000.11.45.1)\nTarget: x86_64-apple-darwin18.5.0\n```\n\nHere you can find other benchmark: [https://github.com/bwhiteley/JSONShootout](https://github.com/bwhiteley/JSONShootout)\n\n## Build \u0026 Run benchmarks\n\n**Prerequisites**\n\nBefore you start to run benchmarks on your device you have to install:\n\n - [Swift](https://swift.org/getting-started/#installing-swift)\n - [.NET Core](https://www.microsoft.com/net/learn/get-started/macos)\n\n When you want to change Swift Protobuf model you need to have additional applications:\n\n - [Google Protobuf compiler](https://github.com/google/protobuf)\n - [Swift Protobuf code generator](https://github.com/apple/swift-protobuf/)\n\n**Build \u0026 Run**\n\nTo build and run you have to execute following commands:\n\n```bash\n$ git clone https://github.com/mczachurski/SwiftBenchmarkJSON.git\n$ cd SwiftBenchmarkJSON\n$ ./build.sh\n$ ./run.sh\n```\n\n## List of frameworks\n\nBelow there are links to all benchmarked frameworks.\n\n - [HandyJSON](https://github.com/alibaba/HandyJSON)\n - [Marshall](https://github.com/utahiosmac/Marshal)\n - [ObjectMapper](https://github.com/Hearst-DD/ObjectMapper)\n - [PMJSON](https://github.com/postmates/PMJSON)\n - [SwiftProtobuf](https://github.com/apple/swift-protobuf.git)\n - Codable - is built in Swift encoding \u0026 decoding based on Codable protocol\n - NetCore - is .NET Core implementation of JSON decoding/encoding (Newtonsoft.JSON framework)\n\n## Encoding (serialization)\n\nBenchmarks of algorithms which transform **object(s)** to the corresponding **JSON string**. Object has structure like on following snippet.\n\n```swift\nTaskClassDto(\n    id: UUID().uuidString,\n    createDate: Date(),\n    name: \"Task 1\",\n    isFinished: false,\n    subtasks: 212,\n    weight: 3.14,\n    children: [\"taska\", \"taskb\", \"taskc\"],\n    description: \"Lorem ipsum dolor sit amet, consectetur adipiscing elit. \n        Aenean eget sem erat. Quisque dictum tellus in feugiat facilisis. \n        Vivamus porttitor vel arcu id cursus. Cras interdum massa ac rhoncus \n        ornare. Sed quis massa felis. Curabitur blandit tempor enim, vitae \n        euismod nibh tincidunt a. Duis faucibus dapibus purus nec dictum. \n        Suspendisse dignissim sapien et consequat lobortis.\",\n    deadline: Date(),\n    tags: [\"tag1\", \"tag2\", \"tag3\", \"tag4\", \"tag5\"]\n)\n```\n\n### Benchmark #1 - Encoding single object\n\nIn this benchmark we are encoding 10,000 times single object. \n\n**Code**\n\nSimple implementation with Swift Codable protocol looks like below.\n\n```swift\nlet entity = TaskDto(...)\n\nlet encoder = JSONEncoder()\nlet formatter = DateFormatter()\nformatter.dateFormat = \"yyyy-MM-dd'T'HH:mm:ssZ\"\nencoder.dateEncodingStrategy = .formatted(formatter)\n\ndo {\n    for _ in 1...10_000 {\n        let jsonData = try encoder.encode(entity)\n        _ = String(data: jsonData, encoding: .utf8)\n    }\n} catch {\n    print(\"Error during serialization object to JSON string: \\(error)\")\n}\n```\n\n**Results**\n\n| Framework     | Run #1 (sec) | Run #2 (sec) | Run #3 (sec) | **Average (sec)** | Ranking             |\n|---------------|--------------|--------------|--------------|-------------------|---------------------|\n| HandyJSON     | 3.967        | 3.825        | 3.863        | **3.885**         | 6                   |\n| Marshall      | 0.484        | 0.486        | 0.476        | **0.482**         | 3 :3rd_place_medal: |\n| ObjectMapper  | 1.162        | 1.138        | 1.048        | **1.116**         | 5                   |\n| PMJSON        | 0.472        | 0.469        | 0.459        | **0.467**         | 2 :2nd_place_medal: |\n| Codable       | 0.708        | 0.705        | 0.702        | **0.705**         | 4                   |\n| SwiftProtobuf | 0.368        | 0.369        | 0.376        | **0.371**         | 1 :1st_place_medal: |\n| NetCore       | 0.093        | 0.089        | 0.087        | **0.090**         | -                   |\n\n\n### Benchmark #2 - Encoding list of objects\n\nIn this benchmark we are encoding 10,000 times list of 100 objects. \n\n**Code**\n\nImplementation with Swift Codable protocol looks like on below snippet.\n\n```swift\nlet list = getListOfTasks() // Returns array of 100 tasks\nlet encoder = JSONEncoder()\n\nlet formatter = DateFormatter()\nformatter.dateFormat = \"yyyy-MM-dd'T'HH:mm:ssZ\"\nencoder.dateEncodingStrategy = .formatted(formatter)\n\ndo {\n    for _ in 1...10_000 {\n        let jsonData = try encoder.encode(list)\n        _ = String(data: jsonData, encoding: .utf8)\n    }\n} catch {\n    print(\"Error during serialization object to JSON string: \\(error)\")\n}\n```\n\n**Results**\n\n| Framework     | Run #1 (sec) | Run #2 (sec) | Run #3 (sec) | **Average (sec)** | Ranking             |\n|---------------|--------------|--------------|--------------|-------------------|---------------------|\n| HandyJSON     | 336.561      | 336.749      | 336.645      | **336.651**       | 6                   |\n| Marshall      | 32.776       | 32.136       | 32.346       | **32.419**        | 1 :1st_place_medal: |\n| ObjectMapper  | 84.854       | 76.278       | 79.348       | **80.160**        | 5                   |\n| PMJSON        | 77.371       | 53.337       | 63.437       | **64.715**        | 4                   |\n| Codable       | 51.383       | 49.456       | 50.355       | **50.398**        | 3 :3rd_place_medal: |\n| SwiftProtobuf | 36.455       | 36.139       | 36.236       | **36.277**        | 2 :2nd_place_medal: |\n| NetCore       | 8.264        | 8.158        | 8.248        | **8.223**         | -                   |\n\n## Decoding (deserialization)\n\nBenchmarks of algorithms which transform JSON to the corresponding object(s). JSON which is parsed looks like on below snippet.\n\n```json\n{\n    \"id\": \"e24e39c2-7b96-4a16-8cb6-bb96239171e5\",\n    \"createDate\": \"2009-02-15T00:00:00Z\",\n    \"name\": \"Task 1\",\n    \"isFinished\": false,\n    \"subtasks\": 212,\n    \"weight\": 3.14,\n    \"children\": [\"taska\", \"taskb\", \"taskc\"],\n    \"description\": \"Lorem ipsum dolor sit amet, consectetur adipiscing elit.\n        Aenean eget sem erat. Quisque dictum tellus in feugiat facilisis. \n        Vivamus porttitor vel arcu id cursus. Cras interdum massa ac rhoncus \n        ornare. Sed quis massa felis. Curabitur blandit tempor enim, vitae \n        euismod nibh tincidunt a. Duis faucibus dapibus purus nec dictum. \n        Suspendisse dignissim sapien et consequat lobortis.\",\n    \"deadline\": \"2019-02-15T01:10:00Z\",\n    \"tags\": [\"tag1\", \"tag2\", \"tag3\", \"tag4\", \"tag5\"]\n}\n```\n\n### Benchmark #3 - Decoding single object\n\nIn this benchmark we are decoding 10,000 times JSON string which represent single object.\n\n**Code**\n\nSimple implementation with Swift Codable protocol.\n\n```swift\nlet jsonData = getJsonData() // Returns Data object (with single JSON object)\nlet decoder = JSONDecoder()\nlet formatter = DateFormatter()\n\nformatter.dateFormat = \"yyyy-MM-dd'T'HH:mm:ssZ\"\ndecoder.dateDecodingStrategy = .formatted(formatter)\n\ndo {\n    for _ in 1...10_000 {\n        let entityJsonData = jsonData.data(using: .utf8)!\n        _ = try decoder.decode(TaskClassDto.self, from: entityJsonData)\n    }\n} catch {\n    print(\"Error during deserialization object from JSON string: \\(error)\")\n}\n```\n\n**Results**\n\n| Framework     | Run #1 (sec) | Run #2 (sec) | Run #3 (sec) | **Average (sec)** | Ranking             |\n|---------------|--------------|--------------|--------------|-------------------|---------------------|\n| HandyJSON     | 3.787        | 3.392        | 3.472        | **3.550**         | 6                   |\n| Marshall      | 1.361        | 1.386        | 1.376        | **1.374**         | 2 :2nd_place_medal: |\n| ObjectMapper  | 1.794        | 1.653        | 1.726        | **1.724**         | 3 :3rd_place_medal: |\n| PMJSON        | 3.804        | 2.020        | 2.721        | **2.848**         | 5                   |\n| Codable       | 1.939        | 1.955        | 1.941        | **1.945**         | 4                   |\n| SwiftProtobuf | 0.204        | 0.194        | 0.198        | **0.199**         | 1 :1st_place_medal: |\n| NetCore       | 0.188        | 0.179        | 0.182        | **0.183**         | -                   |\n\n### Benchmark #4 - Decoding list of objects\n\nIn this benchmark we are decoding 10,000 times JSON string which represent 100 objects.\n\n**Code**\n\nSimple implementation with Swift Codable protocol.\n\n```swift\nlet listJson = getJsonListData() // Returns Data object (with list of JSON objects)\nlet decoder = JSONDecoder()\nlet formatter = DateFormatter()\nformatter.dateFormat = \"yyyy-MM-dd'T'HH:mm:ssZ\"\ndecoder.dateDecodingStrategy = .formatted(formatter)\n\ndo {\n    for _ in 1...10_000 {\n        let listJsonData = listJson.data(using: .utf8)!\n        _ = try decoder.decode([TaskClassDto].self, from: listJsonData)\n    }\n} catch {\n    print(\"Error during deserialization object from JSON: \\(error)\")\n}\n```\n\n**Results**\n\n| Framework     | Run #1 (sec) | Run #2 (sec) | Run #3 (sec) | **Average (sec)** | Ranking             |\n|---------------|--------------|--------------|--------------|-------------------|---------------------|\n| HandyJSON     | 323.744      | 315.371      | 317.336      | **318.817**       | 3 :3rd_place_medal: |\n| Marshall      | 128.328      | 117.112      | 119.214      | **121.551**       | 5                   |\n| ObjectMapper  | 139.405      | 135.547      | 133.544      | **136.165**       | 2 :2nd_place_medal: |\n| PMJSON        | 385.072      | 187.985      | 221.486      | **794,543**       | 4                   |\n| Codable       | 170.782      | 171.822      | 171.321      | **171,308**       | 6                   |\n| SwiftProtobuf | 14.572       | 14.370       | 14.471       | **14,471**        | 1 :1st_place_medal: |\n| NetCore       | 8.368        | 8.283        | 8.189        | **2.367**         | -                   |\n\n## Bonus (Binary SwiftProtobuf)\n\n*SwiftProtobuf* provides additionally binary decoding (instead of JSON string). That kind of encoding/decoding\nis very fast. Below there is table with result for each of above test.\n\n| Test                        | Run #1 (sec) | Run #2 (sec) | Run #3 (sec) | **Average (sec)** |\n|-----------------------------|--------------|--------------|--------------|-------------------|\n| Encoding (single object)    | 0.0459       | 0.0374       | 0.0398       | **0,041**         |\n| Encoding (list of objects)  | 3.458        | 3.480        | 3.472        | **3,470**         |\n| Dencoding (single object)   | 0.0725       | 0.0615       | 0.0707       | **0,068**         |\n| Dencoding (list of objects) | 5.681        | 5.683        | 5.683        | **5,682**         |\n\nIt's fastest decoding/encoding. Unfortunately client have to support that kind of data. However, if\nyour API have to be very fast you should take into account that kind of encoding/decoding.\n\n## Contributing\n\nIf you would like to add another framework for comparison, submit a pull request. Add folder with new benchmark implementation (we have separate application for each framework). Add new framework to `build.sh` and `run.sh` scripts.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmczachurski%2Fswiftbenchmarkjson","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmczachurski%2Fswiftbenchmarkjson","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmczachurski%2Fswiftbenchmarkjson/lists"}