Comments (19)
So sorry I missed these emails. I did find a workaround by using https://godoc.org/github.com/google/jsonapi#Node
directly. It is a little cumbersome, but that's what we get for trying to get Go (with no generics) into a schema like this haha.
from jsonapi.
Apologies to revive this one, but @blainsmith can you provide more details on how you used Node directly to represent different types? I tried using directly six ways to Sunday but I end up with no fields being populated or a type error.
Or is there a specific example that does show how to pull in polymorphic resources like the original Videos/Collections example?
from jsonapi.
I'm not sure that it even makes sense for the data
key to have multiple document types
in it. Side-loaded items in the included
field should do the trick if you need to return documents related to the items in data
.
Additionally, if the items returned in data
are of variable type, then just layer an abstraction on top of them, where they represent some abstract type, and then they could have an attribute which represents their "concrete type" or something of that nature.
Thoughts?
from jsonapi.
Yeah I'm not sure and JSON API wasn't clear on either way. If its an anti-pattern to mix types then we need to fix our use of it. Still unsure though.
from jsonapi.
@blainsmith Maybe if the same struct tag was used for two different related object, it could combine them into a single relationship? This would keep the go end sane, but allow the serialize to create JSON as expected?
from jsonapi.
@genexp Interesting thought, but that would only work one way. It would let you deserialize from JSON -> Struct, but you couldn't serialize from Struct -> JSON since you would loose ordering of the array/slice. You couldn't take different struct properties and merge them into a single JSON array and retain the original/intended order.
This may be a side-effect of the JSON API Spec not considering the type languages in use.
Since the data within relationships
is never a full resource this package should offer an Identifier
type.
type Identifier struct {
ID string `json:"id"`
Type string `json:"type"`
}
Then I can model my structs above as:
type Collection struct {
ID string `json:"id" jsonapi:"primary,collection"`
Title string `json:"title" jsonapi:"attr,title"`
Description string `json:"description" jsonapi:"attr,description"`
Categories []string `json:"categories", jsonapi:"attr,categories"`
Images []*Image `json:"images", jsonapi:"attr,images"`
Entities []*jsonapi.Identifier `json:"entities", jsonapi:"relation:entities"`
}
from jsonapi.
@blainsmith can you please post sample JSON API payloads of what you are trying to accomplish? At first glance I think it would be a bad idea to be able to mix types within a named relationship; but I have not seen in the spec for sure of whether or not this scenario is allowed.
from jsonapi.
Sure the same I have is. The JSON API Spec doesn't say a named relationship cannot have this type of data. I've asked in the forums and read the spec over and over and they do not mention anything about this.
"data": {
"id": "channel-id-personality-1",
"type": "collection",
"attributes": {
"title": "Personality One",
"description": "",
"images": [
{
"url": "https://spaceholder.cc/1920x1080",
"mimeType": "image/jpeg"
}
],
"genres": [],
"releaseDate": null
},
"relationships": {
"entities": {
"data": [
{
"id": "0002f6455e424db5b96214454e6ddb10",
"type": "video"
},
{
"id": "0d387c80d2514597b0365a20a9a586cb",
"type": "video"
},
{
"id": "1204da45e42743b0be3afdc5cf51eeeb",
"type": "video"
},
{
"id": "1252a72ba1684f77815ed26fc63aff0f",
"type": "video"
},
{
"id": "channel-id-clips",
"type": "collection"
},
{
"id": "2990e1185a8e4402b157b57d8eba44d3",
"type": "video"
}
]
}
}
}
from jsonapi.
from jsonapi.
You will also run into this when you respond with include
too. As part of the spec include
is an array of full resources from any number of named relationships. I am wonder if it would be advantageous to define a Resource
type that wraps the actual struct inside of it? That Resource
can also then provide additional methods to assist with reflection and struct manipulation.
package jsonapi
type Resource struct {
ID string
Type string
Value interface{}
}
// Struct methods also for Value reflection?
package my_package
type Collection struct {
ID string `json:"id" jsonapi:"primary,collection"`
Title string `json:"title" jsonapi:"attr,title"`
Description string `json:"description" jsonapi:"attr,description"`
Categories []string `json:"categories", jsonapi:"attr,categories"`
Images []*Image `json:"images", jsonapi:"attr,images"`
Entities []jsonapi.Resource `json:"entities", jsonapi:"relation:entities"`
}
from jsonapi.
@blainsmith the way the library is currently implemented you can definitely have mixed types serialized into the "included"
member. Consider the Go code below; the "included"
member will end up with a mix of Bars
and Bazs
. With that being said you can only define individual relations of a single type.
type Foo struct {
ID string `jsonapi:"primary,foo"`
Bars []*Bar `jsonapi:"relation:bars"`
Bazs []*Baz `jsonapi:"relation:bazs"`
}
This limitation is due to Go's type system. When unmarshalling we try to fully populate the struct(s) of the type defined by the type of the relation ship field (ie Bar
).
I think something similar to what you have proposed could work - the Resource Object definition would also have to include an Attributes
, Relationships
, Links
and Meta
fields. Of course this means to truly have a mixed Go type relation the developer would have to iterate over the []jsonapi.Resource
and determine the appropriate Go Struct type to use for each element.
from jsonapi.
I was trying to marshal a JSON object whose JSONAPI type can only be determined in runtime, so I run into a dead end, because it seems that I am unable to change the type dynamically.
Is this feasible @aren55555?
Thanks
from jsonapi.
@edisonspencer nope that is not possible. This library will only let you marshal structs of fixed type as defined in the struct's field tags (which cannot be modified at runtime)
However with that being said the underlying data structures (particularly Node
) will let you set the "type"
member at runtime - however don't expect to be able to use the publicly available MarshalOnePayload
/MarshalManyPayload
functions.
from jsonapi.
Yes, I understand @aren55555.
Thank you.
from jsonapi.
I'm not sure if this is the same, or only a related issue.
I have a JSON API response, where not (only) the relations have different types, but the top-level data
list as well.
To stick wit the media example: Let's say I have audio
and video
and audio_version
and video_version
respectively. The *_version
types are relations (think e.g. current_version
).
Click to expand JSON example
{
"data": [
{
"id": "62zFbFW0",
"type": "videos",
"attributes": {
"name": "video.m4v",
"created_at": "2017-12-23T18:43:23Z",
"updated_at": "2017-12-23T19:08:33Z"
},
"relationships": {
"current_version": {
"data": {
"id": "rMpIms0M",
"type": "video_versions"
}
},
"versions": {
"data": [
{
"id": "rMpIms0M",
"type": "video_versions"
},
{
"id": "Vj3ZWUp6",
"type": "video_versions"
}
]
}
}
},
{
"id": "Jq3DHQJN",
"type": "videos",
"attributes": {
"name": "video2.m4v",
"created_at": "2017-12-28T14:12:29Z",
"updated_at": "2017-12-28T15:39:58Z"
},
"relationships": {
"current_version": {
"data": {
"id": "oaxu0JsK",
"type": "video_versions"
}
},
"versions": {
"data": [
{
"id": "cjp7GBcO",
"type": "video_versions"
},
{
"id": "t10pkO6y",
"type": "video_versions"
},
{
"id": "SLN8HotW",
"type": "video_versions"
},
{
"id": "oaxu0JsK",
"type": "video_versions"
}
]
}
}
},
{
"id": "vZMZ14pb",
"type": "audios",
"attributes": {
"name": "audio.mp3",
"created_at": "2018-01-02T13:46:24Z",
"updated_at": "2018-01-02T13:46:25Z"
},
"relationships": {
"current_version": {
"data": {
"id": "2dCxDoY3",
"type": "audio_versions"
}
},
"versions": {
"data": [
{
"id": "2dCxDoY3",
"type": "audio_versions"
}
]
}
}
},
{
"id": "1KfW8jB2",
"type": "videos",
"attributes": {
"name": "video.m4v",
"created_at": "2018-01-02T13:55:10Z",
"updated_at": "2018-01-02T14:59:32Z"
},
"relationships": {
"current_version": {
"data": {
"id": "Miq37TkU",
"type": "video_versions"
}
},
"versions": {
"data": [
{
"id": "Miq37TkU",
"type": "video_versions"
}
]
}
}
},
{
"id": "drziqASk",
"type": "audios",
"attributes": {
"name": "another_audio_snippet.mp3",
"created_at": "2018-01-02T14:20:24Z",
"updated_at": "2018-01-02T14:20:24Z"
},
"relationships": {
"current_version": {
"data": {
"id": "fzPFIQfk",
"type": "audio_versions"
}
},
"versions": {
"data": [
{
"id": "fzPFIQfk",
"type": "audio_versions"
}
]
}
}
},
{
"id": "uXxQhqtV",
"type": "videos",
"attributes": {
"name": "video.m4v",
"created_at": "2018-01-03T10:30:25Z",
"updated_at": "2018-01-03T10:30:25Z"
},
"relationships": {
"current_version": {
"data": {
"id": "NvfsGJst",
"type": "video_versions"
}
},
"versions": {
"data": [
{
"id": "NvfsGJst",
"type": "video_versions"
}
]
}
}
}
],
"included": [
]
}
I've omitted the included
objects, but as you can imagine there are different types as well.
I don't quite follow the possible proposed workarounds on how to use jsonapi.UnmarshalManyPayload(apiResponse, …)
to get a list of audio
and video
entries. What do I have to proide as reflect.TypeOf(new(…))
?
I'm quite new to Golang, so excuse me if I just overlooked something very obvious :-/
from jsonapi.
Did any solutions come from this? We also have polymorphic records so have hit this :(
from jsonapi.
@blainsmith did you come up with a solution? Asking because you closed this issue...
from jsonapi.
@blainsmith @tisba any news on this ?
from jsonapi.
@blainsmith can you share your solution?
from jsonapi.
Related Issues (20)
- Type validation on post is skipped
- Support for partial inclusion of relationships
- Asymmetrical behavior with json.RawMessage-type fields
- Community adoption of project HOT 4
- Unmarshall array of object in attribute HOT 1
- map inside struct unmarshalling HOT 2
- Export clearIncluded HOT 1
- got the wrong id when unmarshel a stract with an Int64 id HOT 1
- Is this project active? HOT 4
- Polymorphic relationships HOT 1
- Skipping an element in an array due to unmatched type
- Does example in README have a typo? HOT 1
- int64 id value changed while decoding HOT 12
- Marshal nested object does not work
- data is not a jsonapi representation of *type HOT 2
- Support for Unmarshalling Slices of floats/ints/bools
- Empty relation atrributes HOT 1
- adding meta at time of encoding
- jsonapi.MarshalPayload sets response status to 200, but I want 201 (created) HOT 1
- The wiki shows some weird 'hack' text
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from jsonapi.