j## What's this?
j2s
is a macOS app that converts JSON
dictionaries into Swift struct
s.
No, 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.
If 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 instead.
Yup.
Yeah. j2s
will 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 (exact line of code may change, but look around there for the algorithm).
And, 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.
Also, an Int
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.
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.
j2s
can take in the following JSON
:
{
"outer" : true,
"nested" : {
"what_if_i_want_to" : [
"type? sure, but uncheck the \"Pretty-Print JSON\" box down there --v",
"boogie? wouldn't dream of stopping you"
],
"why" : "to see swift structs over there -->",
"what" : "paste json here",
"cool" : true
}
}
and turn it into Swift code that looks like this:
public struct Root: Codable {
let nested: Nested
let outer: Bool
public struct Nested: Codable {
let cool: Bool
let what: String
let whatIfIWantTo: [String]
let why: String
private enum CodingKeys: String, CodingKey {
case cool
case what
case what_if_i_want_to = "whatIfIWantTo"
case why
}
}
// MARK: -
extension Root.Nested {
static func create(with data: Data) -> Root.Nested {
return JSONDecoder().decode(Root.Nested.self, from: data)
}
static func create(with data: Data) -> [Root.Nested] {
return JSONDecoder().decode([Root.Nested].self, from: data)
}
}
// MARK: -
extension Root {
static func create(with data: Data) -> Root {
return JSONDecoder().decode(Root.self, from: data)
}
static func create(with data: Data) -> [Root] {
return JSONDecoder().decode([Root].self, from: data)
}
}
Optional
s are sort of handled by j2s
. JSON
doesn't have Optional
s, so it's hard to map them over automatically.
While 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
.
The same is also true for properties that show up as null
and as a Type
.
null
s are turned into Any?
.
Yeah. Usually happens in the case of an array of dictionaries. This JSON
:
{
"outer" : true,
"nested" : {
"im_going_to_" : [
"type? sure, but uncheck the \"Pretty-Print JSON\" box down there --v",
"boogie? wouldn't dream of stopping you"
],
"what" : "paste json here"
}
}
will generate this Swift code:
public struct Demo: Codable {
let nested: Nested
let outer: Bool
public struct Nested: Codable {
let imGoingTo: [String]
let what: String
private enum CodingKeys: String, CodingKey {
case im_going_to_ = "imGoingTo"
case what
}
}
private enum CodingKeys: String, CodingKey {
case nested
case outer
}
}
// MARK: -
extension Nested {
static func create(with data: Data) -> Nested {
return JSONDecoder().decode(Nested.self, from: data)
}
static func create(with data: Data) -> [Nested] {
return JSONDecoder().decode([Nested].self, from: data)
}
}
// MARK: -
extension Demo {
static func create(with data: Data) -> Demo {
return JSONDecoder().decode(Demo.self, from: data)
}
static func create(with data: Data) -> [Demo] {
return JSONDecoder().decode([Demo].self, from: data)
}
}
Seemed like a good idea. This was before Codable
was a thing.
A 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.
Before you go, remember that j2s
code is released under a 2-Clause BSD License and all contributions and project activity should be in line with our Code of Conduct.