michiel / jsonapi-rust

Rust library for serialization, deserialization and working with JSON-API data
MIT License
109 stars 29 forks source link

QueryParams, Links, Pagination, and Included Serialization #73

Open ducharmemp opened 4 years ago

ducharmemp commented 4 years ago

Hi there! Great library, I had a few questions after reading the docs and reading through some of the test cases. Some things aren't immediately apparent so I'd love some insight into this or some recommendations.

On a similar vein to question 3, consider the following hierarchy (not entirely valid code)

use models::spam::Spam;

struct Bar {
    id: String,
    spams: Option<Vec<Spam>>
}

jsonapi_model!(Bar; 'bars'; has many spams);

struct Foo {
    id: String,
    bars: Option<Vec<Bar>>;
}

jsonapi_model!(Bar; 'foos'; has many bars);

let bars = vec![Bar::new(), Bar::new(), Bar::new()];
let foo = Foo::new(&bars)

foo.to_jsonapi_document()

This produces the following output (attributes sections omitted since we don't have any):

{
    "data": {
        "type": "foos",
        "id": "1234",
        "relationships": {
            "bars": {
                "data": [
                    { "type": "bars", "id": "31" },
                    { "type": "bars", "id": "32" }
                    { "type": "bars", "id": "33" }
                ]
            }
        }
    },
    "included": [        
        {
            "type": "bars",
            "id": "31",
            "relationships": {
                "spams": {
                    "data": []
                }
            }
        }
        ....rest of the bars
    ]
}

But this makes it seem like I don't have any spams at all, which is totally valid to the perspective of this library because I have't provided that information. This could also be a part of the standard itself, since I've only read through a few of the relevant sections of the spec, but it doesn't seem like included attributes have to provide relationship information. However, even given that limitation, this lib rightfully adds my nested information into the included section of the document. Is it possible to omit the relationship field on nested attributes?

Example JSON doc of what I mean:

{
    "data": {
        "type": "foos",
        "id": "1234",
        "relationships": {
            "bars": {
                "data": [
                    { "type": "bars", "id": "31" },
                    { "type": "bars", "id": "32" }
                    { "type": "bars", "id": "33" }
                ]
            }
        }
    },
    "included": [        
        {
            "type": "bars",
            "id": "31",
            "relationships": {
                "spams": {
                    "data": [
                        { "type": "spams", "id": "uuid-84848" }
                    ]
                }
            }
        }
        ....rest of the bars
        {
            // This shouldn't exist
            "type": "spams",
            "id": "uuid-84848",
            "attributes": {
                ...attrs
            }
        }
    ]
}

Again I'd love to help out with figuring this out since this lib seems very focused and very well made!

Edit: I think part of the last point could be fixed if serde's skip_if directive was taken into account for the relationship fields? I can skip serializing the main attributes but not any relationship fields, they just default to an empty slice.

JadedEvan commented 4 years ago

@ducharmemp hi there! I wanted to chime in with some info on some of the comments that you've made. In particular:

What's the recommended way to construct links? Same question as above for pagination attributes

Unfortunately in my experience with the jsonapi_model! macro I don't feel that it is currently robust enough to easily support more advanced document structure that may include link and pagination attributes.

I found the most effective way to respond with the correct link and pagination attributes was simply to manipulate the top-level JSONAPI document. I can help provide some examples of this kind of manipulation if that would be helpful.

I think the right solution to your inquiries is to write some code and get some test cases to demonstrate this behavior. I find examples in these kind of libraries immensely helpful - I'll see about putting some time into that