{"id":13634077,"url":"https://github.com/zadr/j2s","last_synced_at":"2025-04-10T00:18:15.217Z","repository":{"id":136430283,"uuid":"77762829","full_name":"zadr/j2s","owner":"zadr","description":"A macOS app to convert JSON to Swift structs","archived":false,"fork":false,"pushed_at":"2023-07-31T06:22:56.000Z","size":2273,"stargazers_count":234,"open_issues_count":5,"forks_count":14,"subscribers_count":5,"default_branch":"main","last_synced_at":"2025-04-10T00:18:09.812Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zadr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2017-01-01T02:14:33.000Z","updated_at":"2025-03-24T19:11:51.000Z","dependencies_parsed_at":"2024-01-02T21:54:18.192Z","dependency_job_id":"c5fc62cd-899a-404b-9c37-37a96beb306a","html_url":"https://github.com/zadr/j2s","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/zadr%2Fj2s","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zadr%2Fj2s/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zadr%2Fj2s/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zadr%2Fj2s/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zadr","download_url":"https://codeload.github.com/zadr/j2s/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248131318,"owners_count":21052820,"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":[],"created_at":"2024-08-01T23:00:56.513Z","updated_at":"2025-04-10T00:18:15.197Z","avatar_url":"https://github.com/zadr.png","language":"Swift","funding_links":[],"categories":["Applications","Swift","Development"],"sub_categories":["Development","JSON Parsing","👨‍💻 Development (9)"],"readme":"## What's this?\n`j2s` is a macOS app that converts [`JSON`](https://en.wikipedia.org/wiki/JSON) dictionaries into [Swift](https://swift.org) `struct`s.\n\n![Screenshot](Screenshot.png?raw=true)\n\n## That's it? Can I make it do anything else?\nNo, yeah, that's it. You give `j2s` a `json` file, and it gives you Swift `struct`s. You can pick if it outputs to one file or a _n_ files for _n_ `struct`s.\n\nIf you want to make it do anything else, you'll have to write some more code. I'll probably accept pull requests, but, you should probably look into other tools like [Sourcery](https://github.com/krzysztofzablocki/Sourcery) instead.\n\n## Codable-compliant `struct`s, right?\nYup.\n\n## Cool\nYeah. `j2s` will also convert `snake_case_key_names` into `camelCasePropertyNames`, and if you have a key where the value is an array of of dictionaries, the key name will be — naively — [depluralized](https://github.com/zadr/j2s/blob/main/j2s/StringTransformations.swift#L14) (exact line of code may change, but look around there for the algorithm).\n\nAnd, if your `JSON` value is a string that's secretly a `Date` in a format that `j2s` understands (Currently: `ISO8601`), the generated code will use the correct (`Date`) type.\n\nAlso, an integer like `5` is an `Int` and a floating point number like `5.0` is a `Double`. Because, you know, thats how these things should work.\n\n## What version of Swift does this target?\n`j2s.xcodeproj` requires Swift 4 (Xcode 9 or greater) to build. The code it outputs requires Swift 4. If you need Swift 3 support, try looking back in commit history for an older version.\n\n## What's the generated code look like?\n\n`j2s` can take in the following `JSON`:\n\n```json\n{\n  \"outer\" : true,\n  \"nested\" : {\n    \"what_if_i_want_to\" : [\n      \"boogie? wouldn't dream of stopping you\"\n    ],\n    \"when\" : \"2017-06-27T17:58:28+00:00\",\n    \"cool\" : true\n  }\n}\n```\n\nand turn it into Swift code that looks like this:\n\n```swift\npublic struct Root: Codable {\n\tpublic let nested: Nested\n\tpublic let outer: Bool\n\n\tpublic struct Nested: Codable {\n\t\tpublic let cool: Bool\n\t\tpublic let whatIfIWantTo: [String]\n\t\tpublic let when: Date\n\t\t}\n}\n\n// MARK: -\n\npublic extension Root {\n\tstatic func create(with data: Data) throws -\u003e Root  {\n\t\treturn try JSONDecoder().decode(Root.self, from: data)\n\t}\n\n\tstatic func create(with data: Data) throws -\u003e [Root]  {\n\t\treturn try JSONDecoder().decode([Root].self, from: data)\n\t}\n}\n\n// MARK: -\n\npublic extension Root.Nested {\n\tstatic func create(with data: Data) throws -\u003e Root.Nested  {\n\t\tlet decoder = JSONDecoder()\n\t\tdecoder.dateDecodingStrategy = .iso8601\n\t\treturn try decoder.decode(Root.Nested.self, from: data)\n\t}\n\n\tstatic func create(with data: Data) throws -\u003e [Root.Nested]  {\n\t\tlet decoder = JSONDecoder()\n\t\tdecoder.dateDecodingStrategy = .iso8601\n\t\treturn try decoder.decode([Root.Nested].self, from: data)\n\t}\n}\n```\n\n## What about `Optional`s? I heard Swift has `Optional`s, but, I don't see any `Optional`s.\n`Optional`s are sort of handled by `j2s`. `JSON` doesn't have `Optional`s, so it's hard to map them over automatically.\n\nWhile parsing, if `j2s` is told to create the same `struct` multiple times, it considers any properties that don't exist in both models to be [`Optional`](http://swiftdoc.org/v3.0/type/Optional/).\n\nThe same is also true for properties that show up as `null` and as a `Type`.\n\n`null`s are turned into `Any?`.\n\n## Oh.\nYeah. Usually happens in the case of an array of dictionaries. This `JSON`:\n\n```json\n{\n  \"outer\" : true,\n  \"nested\" : {\n    \"im_going_to_\" : [\n      \"type? sure, but uncheck the \\\"Pretty-Print JSON\\\" box down there --v\",\n      \"boogie? wouldn't dream of stopping you\"\n    ],\n    \"what\" : \"paste json here\"\n  }\n}\n```\n\nwill generate this Swift code:\n\n```swift\npublic struct Demo: Codable {\n\tpublic let nested: Nested\n\tpublic let outer: Bool\n\n\tpublic struct Nested: Codable {\n\t\tpublic let imGoingTo: [String]\n\t\tpublic let what: String\n\t}\n}\n\n// MARK: -\n\npublic extension Nested {\n\tpublic static func create(with data: Data) throws -\u003e Nested  {\n\t\treturn try JSONDecoder().decode(Nested.self, from: data)\n\t}\n\n\tpublic static func create(with data: Data) throws -\u003e [Nested]  {\n\t\treturn try JSONDecoder().decode([Nested].self, from: data)\n\t}\n}\n\n// MARK: -\n\npublic extension Demo {\n\tpublic static func create(with data: Data) throws -\u003e Demo  {\n\t\treturn try JSONDecoder().decode(Demo.self, from: data)\n\t}\n\n\tpublic static func create(with data: Data) throws -\u003e [Demo]  {\n\t\treturn try JSONDecoder().decode([Demo].self, from: data)\n\t}\n}\n```\n\n## Why build this and not use some other tool?\nSeemed like a good idea. This was before `Codable` was a thing.\n\n## Still hung up on depluralization? (Singularity?)\nA `JSON` dictionary with a key named `potatoes`, where the value is a list of dictionaries will be given the Swift type `[Potato]`. Similarly, `soliloquies` becomes `[Soliloquy]`, `dwarves` and `[Dwarf]`, and so on. Depluralization is a giant `if` statement though, so while `indices` becomes `[Index]`, `matrices` incorrectly becomes `matrex`. If Anyone wanted to do some natural language processing to solve this, that would be cool.\n\n## Okay then\nBefore you go, remember that `j2s` code is released under a [2-Clause BSD License](LICENSE.md) and all contributions and project activity should be in line with our [Code of Conduct](CODE_OF_CONDUCT.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzadr%2Fj2s","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzadr%2Fj2s","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzadr%2Fj2s/lists"}