JSONAPI
JSONAPI copied to clipboard
Redesign Attributes/Relationships around property wrappers
Exploration started here: https://github.com/mattpolzin/JSONAPI/tree/feature/transformed-property
This project is on hold until property wrapper chaining (or nesting) is supported (likely Swift 5.2).
The idea I am pursuing is to replace Attribute/TransformedAttribute with an @Attribute attribute and use an @Omittable attribute to represent when attributes can be omitted (i.e. the key is not required). I am a little less solid on relationships, but they would get similar treatment. Then, I additionally would like to flatten things so that attributes and relationships are defined in the same structure with their property attributes being the thing that differentiates them. Definitely have not worked out all of the details yet, but I hope that in addition to being a breaking change this will bring some concision and reduce the overall number of types needed a bit.
Something like
PersonProperties {
// takes the place of current `Attribute`
@Attribute
var name: String
// where age is stored as a `String` for some reason but we expect it to always be an `Int`
// takes the place of current `TransformedAttribute`
@Attribute(deserialize: StringToInt.self)
var age: Int
// takes the place of current `ToOneRelationship`
@Relationship(to: City?.self)
var hometown: Id?
// takes the place of current `ToManyRelationship`
@Relationship(to: [Person].self)
var friends: [Id]
}
I think that's the biggest barrier of entry for new developers when adopting this library. The example code is easy to use; but understanding what's under the hood it's "advanced" Swift (maybe for me, I co-own a small developer company in Mexico, so I don't get the luxury to specialize in any language) and implementing this code was a little daunting for me.
Also you end up working with objects that are not what you usually are accustomed to. PropertyWrappers make the code more readable, and people don't really need to understand how they do things to use them.
If we could go from this
let name = person.attributes.name.value
to
let name = person.name
I bet adoption of this library would go through the roof.
I do still want to explore using Property Wrappers or even Function Builders for this library. Function Builders especially could be cool, but they are only now gaining some of their more useful features (from an API development perspective) and even at that they aren't officially part of the language just yet.
@mlomeli :
... If we could go from this
let name = person.attributes.name.valuetolet name = person.name...
Specifically this point seems to be looking for something that this library does already offer via dynamic callable. Are you getting an error when you write let name = person.name (to use your example)? That should be equivalent to writing let name = person.attribute.name.value unless there's ambiguity the compiler can't sort out.
Sweet! Just tested it. No, I don't get an error. I just didn't know you could call it like that. Even though it's right there in the Examples. Guess I'm over-reliant on autocomplete.
Thanks!
Hi @mattpolzin is it possible to use Swift Macros to remove a lot of types and boilerplate code already? I was thinking something like being able to do the following:
@JSONAPIResource
struct Person {
@Attribute("name") var name: String
@ToOne("house") var house: House
@ToMany("siblings") var siblings [Person]
}
I haven't looked into them already but from what I understood this could be achieved. Would love to hear your thoughts
I suspect that macros could be very useful here. I haven’t been coding in Swift enough lately to have found the time to get up to speed on Swift Macros, though.
The tricky thing would be maintaining the “soul” of this JSON:API library while also adopting a new tech like property wrappers or macros. That’s pretty vague, but maybe it makes some sense?
In short, I’d be excited to see boilerplate reduced and I’d be excited to see mundane developer tasks automated as long as the library stayed codable, type safe, declarative, etc.