mattpolzin / JSONAPI

Swift Codable JSON:API framework
MIT License
75 stars 19 forks source link

How to define heterogenous resource object types in a batch document? #95

Closed russellyeo closed 3 years ago

russellyeo commented 3 years ago

Thanks for open-sourcing this library, I've found it really useful!

Is it possible to use this library to define a batch document with different types? e.g.

{
    "data": [
        {
            "id": "1",
            "type": "dog",
            "attributes": {
                "color": "black"
            }
        },
        {
            "id": "2",
            "type": "cat",
            "attributes": {
                "color": "white"
            }
        }
    ]
}

As far as I can tell this is not possible because a ResourceObject takes a type parameter ResourceObjectDescription which can only have one jsonType.

typealias BatchDocument<Resource: ResourceObjectType> = JSONAPI.Document<ManyResourceBody<Resource>, NoMetadata, NoLinks, NoIncludes, NoAPIDescription, UnknownJSONAPIError>

typealias AnimalsDocument = BatchDocument<JSONAPI.ResourceObject<AnimalDescription, NoMetadata, NoLinks, String>>

struct AnimalDescription: ResourceObjectDescription {
    static let jsonType: String = "animal"

    struct Attributes: JSONAPI.Attributes {
        public let color: Attribute<String>
    }
    public typealias Relationships = NoRelationships
}

Perhaps there is another way to define a document with a heterogenous list of resource objects?

mattpolzin commented 3 years ago

Hi! Glad the library has been useful.

You can do what you are trying to do using the Poly type as long as you expect no more than 11 different primary resource types.

I've expanded the examples a bit in response to this question here.

To more directly address your code above, you would need to loosen the definition of BatchDocument a bit because a Poly is not a ResourceObjectType, it is just a thing that can represent any number of other types (and in this case any number of ResourceObjectTypes). This is ok because ManyResourceBody does not actually require its type parameter to be a ResourceObjectType, it just requires it to be an EncodablePrimaryResource (and Poly works for that).

Let me know if you've got any remaining questions about how to implement this; it is very doable, but there are subtle differences (like how to define the BatchDocument typealias or the fact that you are going to want to actually pull Cat or Dog types out of your Poly to use them unless you want to conform Poly2<Dog,Cat> to a shared Animal protocol that exposes properties both types have).

mattpolzin commented 3 years ago

I'm going to close this question as answered and also because it prompted me to add some more examples to the documentation which is now done.

Please still feel free to reply with follow-up questions, requests, or feedback based on this ticket!