Skip to content

Is it possible to Unmarshal into a map? #53

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
nodefortytwo opened this issue Oct 4, 2016 · 7 comments
Closed

Is it possible to Unmarshal into a map? #53

nodefortytwo opened this issue Oct 4, 2016 · 7 comments

Comments

@nodefortytwo
Copy link

I can't seem to get this to work:

type Player struct {
    ID   int    `jsonapi:"primary,players"`
    Path string `jsonapi:"attr,path"`
    //Failing with data is not a jsonapi representation of '*main.Player'
    Files map[string]*File `jsonapi:"attr,files"`
}

type File struct {
    Path  string    `jsonapi:"attr,path"`
    isDir bool `jsonapi:"attr,isDir"`
    time  time.Time `jsonapi:"attr,time"`
}
{
    data: {
        type: "players",
        id: "71776400",
        attributes: {
            path: "/no/dnb/71776400",
            files: {
                meta.json.js: {
                    path: "/vlah/",
                    isDir: false,
                    time: "2016-10-04T00:59:12+00:00"
                },
                tine-sunniva: {
                    id: "6a342e32-3aad-41f2-86bd-721170d02718",
                    path: /blah",
                    isDir: true,
                    time: "2016-10-04T00:59:12+00:00",
                    atomic: true
                }
            }
        },
        links: {
            self: "https://blah/api/v2/players/71776400"
        }
    }
}
@aren55555
Copy link
Contributor

aren55555 commented Oct 4, 2016

Unfortunately an attr field of type map[string]foo will just result in errors (like the one you are seeing). Currently this library does not provide support to Marshal or Unmarshal the nested attributes as provided in your example JSON payload; see #49 and #21 for similar discussion. With that being said we would appreciate any PR adding such support!

Library support aside, I think in your specific case you may want to consider each File as a relation to the Player; such that a Player would have many Files. Currently you are using the Player attributes to describe many files. Per the spec the attributes object should only model information about the resource object (in this case players) - it seems like path, isDir and time are not describing players but rather files. I'd suggest something akin to:

type Player struct {
    ID    int    `jsonapi:"primary,players"`
    Path  string `jsonapi:"attr,path"`
    Files *File  `jsonapi:"relation,files"`
}

type File struct {
    Name  string    `jsonapi:"primary,files"`
    Path  string    `jsonapi:"attr,path"`
    isDir bool      `jsonapi:"attr,isDir"`
    time  time.Time `jsonapi:"attr,time"`
}

@nodefortytwo
Copy link
Author

Thanks for the response, I do agree in principle that the schema is.. confused however this is a bit of a legacy api and changes can't be made easily.

I will investigate adding nested attribute support to the library.

@shwoodard
Copy link
Contributor

@aren55555 @nodefortytwo does the jsonapi spec permit such attribute configuration?

@aren55555
Copy link
Contributor

@shwoodard yes the JSON API spec does permit this configuration; take a look at http://jsonapi.org/format/#document-resource-object-attributes:

Attributes

The value of the attributes key MUST be an object (an “attributes object”). Members of the attributes object (“attributes”) represent information about the resource object in which it’s defined.

Attributes may contain any valid JSON value.

Complex data structures involving JSON objects and arrays are allowed as attribute values. However, any object that constitutes or is contained in an attribute MUST NOT contain a relationships or links member, as those members are reserved by this specification for future use.

Although has-one foreign keys (e.g. author_id) are often stored internally alongside other information to be represented in a resource object, these keys SHOULD NOT appear as attributes.

@aren55555
Copy link
Contributor

aren55555 commented Oct 4, 2016

@nodefortytwo in looking at this again I also noticed all the keys in your sample JSON payload are not strings; ie data: vs "data": - not sure if this was an off hand example or an actual payload; but I thought I would point this out.

That payload will cause an error outside of the JSON API library; it will fail the vanilla go JSON unmarshal.

@aren55555
Copy link
Contributor

aren55555 commented Oct 4, 2016

I should also mention that I have been working on a JSON API payload validator... its a WIP so it's not yet perfect, but it will catch anything really obvious/easy to implement: http://corroborate.arenpatel.com/

{
    "data": {
        "type": "players",
        "id": "71776400",
        "attributes": {
            "path": "/no/dnb/71776400",
            "files": {
                "meta.json.js": {
                    "path": "/vlah/",
                    "isDir": false,
                    "time": "2016-10-04T00:59:12+00:00"
                },
                "tine-sunniva": {
                    "id": "6a342e32-3aad-41f2-86bd-721170d02718",
                    "path": "/blah",
                    "isDir": true,
                    "time": "2016-10-04T00:59:12+00:00",
                    "atomic": true
                }
            }
        },
        "links": {
            "self": "https://blah/api/v2/players/71776400"
        }
    }
}

That payload shows results in no errors/warnings.

@nodefortytwo
Copy link
Author

Sorry just got the notification about this.

the data vs "data" thing was caused by copying from JSON View :)

JSON validator is cool, I generally use pro.jsonlint.com

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants