{"id":19784734,"url":"https://github.com/mikehouse/sortedjsoncoder","last_synced_at":"2026-05-05T10:34:42.758Z","repository":{"id":42332080,"uuid":"273726545","full_name":"mikehouse/SortedJSONCoder","owner":"mikehouse","description":"Library for sorted/ordered JSON serialisation/encoding in Swift and Objective-C","archived":false,"fork":false,"pushed_at":"2022-07-05T10:57:49.000Z","size":118,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-01-11T02:52:23.580Z","etag":null,"topics":["cocoapods","encoding","json","objective-c","serialization","sorting","swift"],"latest_commit_sha":null,"homepage":"","language":"Objective-C","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/mikehouse.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":"2020-06-20T14:44:44.000Z","updated_at":"2022-07-05T09:42:59.000Z","dependencies_parsed_at":"2022-09-21T16:53:19.670Z","dependency_job_id":null,"html_url":"https://github.com/mikehouse/SortedJSONCoder","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mikehouse%2FSortedJSONCoder","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mikehouse%2FSortedJSONCoder/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mikehouse%2FSortedJSONCoder/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mikehouse%2FSortedJSONCoder/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mikehouse","download_url":"https://codeload.github.com/mikehouse/SortedJSONCoder/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241117245,"owners_count":19912508,"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":["cocoapods","encoding","json","objective-c","serialization","sorting","swift"],"created_at":"2024-11-12T06:12:29.949Z","updated_at":"2026-05-05T10:34:42.713Z","avatar_url":"https://github.com/mikehouse.png","language":"Objective-C","funding_links":[],"categories":[],"sub_categories":[],"readme":"**SortedJSONCoder** is a library for encoding/serialization objects to JSON preserving some sorting rules. Written in Objective-C.\n\n## Credits\n\n95% of code is third-party dependencies:\n\n- JSON encoder/decoder https://github.com/TouchCode/TouchJSON\n- An ordered dictionary https://github.com/Marxon13/M13OrderedDictionary \n\n## Support\n\n- Swift\n- Objective-C\n\n## Installation\n\n### Cocoapods\n\n```ruby\npod 'SortedJSONCoder', :git =\u003e 'https://github.com/mikehouse/SortedJSONCoder.git', :commit =\u003e 'cc868564'\n```\nNo way make support of `SPM` and `Carthage` as used third-party libraries do not support these.  \n \n## Interface\n\n### Objective-C\n\n```objectivec\n@interface SortedJSONEncoder : NSObject\n\n- (instancetype)init;\n\n- (NSData *)encode:(NSDictionary *)jsonObject\n           options:(NSStringCompareOptions)options\n             error:(NSError **)error;\n\n- (NSData *)encode:(NSDictionary *)jsonObject\n        comparator:(NSComparisonResult (^)(NSString *, NSString *))comparator\n             error:(NSError **)error;\n\n@end\n```\n\n### Swift\n\n```swift\nclass SortedJSONEncoder {\n\n    init()\n\n    func encode(_ jsonObject: [AnyHashable : Any], \n                     options: NSString.CompareOptions = []) throws -\u003e Data\n\n    func encode(_ jsonObject: [AnyHashable : Any], \n                  comparator: @escaping (String, String) -\u003e ComparisonResult) throws -\u003e Data\n}\n\n```\n \n## Usage\n \n### Objective-C\n \n```objectivec\n#import \u003cSortedJSONCoder/SortedJSONEncoder.h\u003e\n\n- (void)writeJSON:(NSDictionary *)object toPath:(NSURL *)path {\n    SortedJSONEncoder *encoder = [SortedJSONEncoder new];\n    NSData *data = [encoder encode:object options:NSCaseInsensitiveSearch error:nil];\n    [data writeToURL:path atomically:YES];\n}\n```\n \nLocalized case insensitive order:\n \n```objectivec\n#import \u003cSortedJSONCoder/SortedJSONEncoder.h\u003e\n\n- (void)writeJSON2:(NSDictionary *)object toPath:(NSURL *)path {\n    SortedJSONEncoder *encoder = [SortedJSONEncoder new];\n    NSData *data = [encoder encode:object comparator:^NSComparisonResult(NSString *s1, NSString *s2) {\n            return [s1 localizedCaseInsensitiveCompare:s2];\n        } error:nil];\n    [data writeToURL:path atomically:YES];\n}\n```\n\n### Swift\n\n```swift\nimport SortedJSONCoder\n\nlet encoder = SortedJSONEncoder()\nlet dict: [String:Any] = [\"a\":1];\nlet data = try encoder.encode(dict, options: .literal)\ntry data.write(to: URL(string: \"/path/to/out.json\")!)\n```\n\nCustom order logic:\n\n```swift\nimport SortedJSONCoder\n\nlet encoder = SortedJSONEncoder()\nlet dict: [String:Any] = [\"a\":1];\nlet data = try encoder.encode(dict, comparator: { (s1: String, s2: String) -\u003e ComparisonResult in\n    if s1 == s2 { return .orderedSame }\n    else if s1 \u003c s2 { return .orderedAscending }\n    else { return .orderedDescending }\n})\ntry data.write(to: URL(string: \"/path/to/out.json\")!)\n```\n\n#### Pretty Printed \n\n```swift\nlet encoder = SortedJSONEncoder()\nencoder.pretty = true\n```\n\n## Why ?\n\nSay we have a json file from server side:\n\n```json\n{\n    \"payload\": {\n        \"prop1_key\": \"prop1_value\",\n        \"prop2_key\": \"prop2_value\"\n    },\n    \"sha256\": \"bd575a7f4028fe0b195682193c99eaa734e62def4790280394807068727a4539\"\n}\n```\n\nwhere `sha256` is SHA256 hash for payload's json data, that is\n\n```objectivec\nNSData *jsonData = [[NSData alloc] initWithContentsOfFile:@\"/path/to/server.json\"];\nNSDictionary *jsonObject = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:nil];\nNSDictionary *payload = jsonObject[@\"payload\"];\nNSData *payloadData = [NSJSONSerialization dataWithJSONObject:payload options:NSJSONWritingSortedKeys error:nil];\n\nNSString *expectedSHA256 = jsonObject[@\"sha256\"];\nNSString *actualSHA256 = [[payloadData sha256] hex];\n\nXCTAssertEqual(expectedSHA256, actualSHA256);\n```\n\nAs you can see this hash check may fail when backend and iOS use different algorithms for keys sorting for JSON serialization, moreover on iOS standard SDK no way use different/custom sorting algorithm as only one available is system one. And here this library can help, where you can provide any you'd like sorting algorithm for JSON encoding.\n\nSwift version of this logic:\n\n```swift\nstruct Root: Codable {\n    let payload: Payload\n    let sha256: String\n    struct Payload: Codable {\n        let prop1_key: String\n        let prop2_key: String\n    }\n}\n\nlet rootJSONData: Data = try Data(contentsOf: URL(string: \"/path/to/server.json\")!)\nlet rootObject: Root = try JSONDecoder().decode(Root.self, from: rootJSONData)\nlet payloadJSONData = try JSONEncoder().encode(rootObject.payload)\nlet payloadJSONObject = try JSONSerialization.jsonObject(with: payloadJSONData, options: []) as! [AnyHashable : Any]\n\nlet sortedPayloadData = try SortedJSONEncoder().encode(payloadJSONObject, options: .caseInsensitive)\nlet sha256: String = sortedPayloadData.sha256.hex()\n\nassert(sha256 == rootObject.sha256)\n```\n\n## Tests\n\nBase cases covered.\n\n## TODO\n\n- Pretty json formatting\n- Support custom indents for json elements\n \n## License\n\nThe code of this library itself - MIT   \nhttps://github.com/TouchCode/TouchJSON - FreeBSD License   \nhttps://github.com/Marxon13/M13OrderedDictionary - MIT\n \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmikehouse%2Fsortedjsoncoder","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmikehouse%2Fsortedjsoncoder","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmikehouse%2Fsortedjsoncoder/lists"}