api2go
api2go copied to clipboard
api2go jsonapi client
It would be awesome if we could use api2go as a golang client, accessing a jsonapi server. Most of the functionality is currently in place, however this seems like it makes sense to do this after the Unmarshal refactorization (#111) project is done.
We would need to add support for Unmarshaling 'Composer Documents': http://jsonapi.org/format/#document-structure-compound-documents
+1 I'm very looking forward to this.
good to know! Any special requirements we should keep in mind?
Well, I'm a novice at Go, so I don't have any idea but well written documents would help users like me, I guess. I have JSON API written in Rails and just started to develop a CLI for that.
Oh I think it would be nice that api2go could do like this:
var posts []Post
body, err := ioutil.ReadAll(response.Body) // net/http
api2go.Unmarshal(body, posts)
if you only have simple posts without compound objects, it should already work. Currently only our marshaller supports the generation of a json with compound objects included in it. We have to add this feature to the unmarshaller too.
It has relationships in it. Is that what you mean by "compound objects"?
I'm trying to unmarshal the data but I get []. :cry: I think I'm doing something wrong but I still don't know the right way.
as long as you only have relationship IDs, it should work, because that is what works when you use it server-side. Compound objects are objects that you can find under the included key in the json. For example if you send a blog post including the comment objects.
I'm sorry. I still can't understand. I wrote code like this.
type App struct {
Id string `jsonapi:"primary,apps"`
Name string `jsonapi:"attr,name"`
CreatedAt time.Time `jsonapi:"attr,created_at"`
UpdatedAt time.Time `jsonapi:"attr,updated_at"`
Images []*Image `jsonapi:"relation,images"`
}
type Image struct {
Id string `jsonapi:"-"`
ImageName string `jsonapi:"-"`
CreatedAt time.Time `jsonapi:"-"`
UpdatedAt time.Time `jsonapi:"-"`
App App `jsonapi:"-"`
}
func main() {
client := &http.Client{}
req, err := http.NewRequest("GET", "http://localhost:3000/apps", nil)
resp, err := client.Do(req)
body, err := ioutil.ReadAll(resp.Body)
}
How can I unmarshal the body ?
are you sure that you are even using our package? we do not provide annotations that you posted in your code snippet. But this is getting offtopic for this ticket, please use our gitter chatroom or let's discuss this in another ticket.
Oh, I'm sorry. I'll join the chat room.
no worries ;) thx!
now that we have refactored the Unmarshaling part we can think about this again too.
What needs to be done to support everything from a clients perspective is the support for unmarshaling of included/compound objects, right? So we need a way to specify more than the one target to unmarshal into. We need some good solution to pass multiple targets for expected included objects too. The unmarshaler will then unmarshal the correct objects in the correct structs or slices
I am thinking about something like this if you load a BlogPost that has an Author and Comments:
included := map[string]interface{}{
"author": &Author{},
"comments": []Comment{},
}
UnmarshalWithIncluded(json []byte, target interface{}, included map[string]interface{}) error
our main jsonapi Document looks like this currently:
type Document struct {
Links *Links `json:"links,omitempty"`
Data *DataContainer `json:"data"`
Included []Data `json:"included,omitempty"`
Meta map[string]interface{} `json:"meta,omitempty"`
}
So, included stuff is just a []Data and we can go through that and unmarshal it into the included map
type Data struct {
Type string `json:"type"`
ID string `json:"id"`
Attributes json.RawMessage `json:"attributes"`
Relationships map[string]Relationship `json:"relationships,omitempty"`
Links *Links `json:"links,omitempty"`
}
The Type field indicates which included Data struct must be unmarshalled into which struct/slice in the included map.
Does somebody have a better idea?