Giter Site home page Giter Site logo

Relationship Types about jsonapi HOT 19 CLOSED

google avatar google commented on August 24, 2024 3
Relationship Types

from jsonapi.

Comments (19)

blainsmith avatar blainsmith commented on August 24, 2024 1

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.

JimFicarra avatar JimFicarra commented on August 24, 2024 1

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.

thedodd avatar thedodd commented on August 24, 2024

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.

blainsmith avatar blainsmith commented on August 24, 2024

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.

svperfecta avatar svperfecta commented on August 24, 2024

@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.

blainsmith avatar blainsmith commented on August 24, 2024

@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.

aren55555 avatar aren55555 commented on August 24, 2024

@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.

blainsmith avatar blainsmith commented on August 24, 2024

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.

svperfecta avatar svperfecta commented on August 24, 2024

from jsonapi.

blainsmith avatar blainsmith commented on August 24, 2024

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.

aren55555 avatar aren55555 commented on August 24, 2024

@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.

edisonspencer avatar edisonspencer commented on August 24, 2024

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.

aren55555 avatar aren55555 commented on August 24, 2024

@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.

edisonspencer avatar edisonspencer commented on August 24, 2024

Yes, I understand @aren55555.
Thank you.

from jsonapi.

tisba avatar tisba commented on August 24, 2024

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.

adamlc avatar adamlc commented on August 24, 2024

Did any solutions come from this? We also have polymorphic records so have hit this :(

from jsonapi.

tisba avatar tisba commented on August 24, 2024

@blainsmith did you come up with a solution? Asking because you closed this issue...

from jsonapi.

nilsonsrjunior avatar nilsonsrjunior commented on August 24, 2024

@blainsmith @tisba any news on this ?

from jsonapi.

gadelkareem avatar gadelkareem commented on August 24, 2024

@blainsmith can you share your solution?

from jsonapi.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.