HAL/json implementation

505 views
Skip to first unread message

Nicolas Vellon

unread,
Nov 30, 2014, 9:34:44 PM11/30/14
to golan...@googlegroups.com
Hey guys,

I've recentrly been in talk by Brad Fritz, and got very motivated to give a try on Golang.

So I made this kind of HAL media type implentation, as some sort of "hello world" project.

The basic idea was to have an easy way to translate a given set of structs/objects into this hal+json structures, keeping the "business structs" clean of funny composing magic... Had a bit of a difficult time until I got how to implement oop basics, interfaces and all that stuff, but got it woring.


If any of you (experienced gophers) have a chance to take a look and maybe give some feedback, it will be much apreciated.

Thanks!

Klaus Post

unread,
Dec 1, 2014, 7:21:45 AM12/1/14
to golan...@googlegroups.com
Hi!

I'm not a guru, but since nobody else responded, I thought I might give you my thoughts.

Overall it looks very good, I don't know HAL links into details, but your implementation seem nice.

First, name your package "hal". Other people using it will have to use "gohal", which isn't really needed to know what they are dealing with.

I would personally either:
a) call "Encode" function something a bit more descriptive, like EncodeHal, or
b) make a type Hal ap[string]interface{}, so the interface has to return a specific type, that way you don't get accidental clashes, and you are type safe.

I implemented "b)": https://github.com/klauspost/gohal/tree/master  - Notice how much cleaner things become with that simple change.


I am still not really sure how this is intended to be used. It seems quite a bit bothersome to have to implement "Encode" for all my types. I would think the best way would be to use an anonymous field in my struct, so I can use the standard JSON encoding functions in golang. I will try to see if I can give you an example, since it isn't that trivial.

/Klaus

Klaus Post

unread,
Dec 1, 2014, 10:04:06 AM12/1/14
to golan...@googlegroups.com
Hi again!

I re-implemented the library, like I would probably do it:

https://github.com/klauspost/gohal/tree/less-magic

I have updated the library and the example.

It is now much simpler to use, you now just add an anonymous field to your struct:

* No custom interfaces to satify.
* No need for custom encoders, you serialize it as any object.
* Just include *hal.Resource in your struct.
* If you don't initialize ".Resource", it is ignored when Marshalling
* Add "Self" link to structs for convenience.

Other minor things:
* Return pointers from "NewXxxx" - that seems to be good practice.
* Use names when initializing structs - just nice for readability and maintainability.

So now, there is only one custom marshaller for links, the rest is using standard golang.

Does this make any sense?

Máximo Cuadros

unread,
Dec 1, 2014, 11:18:06 AM12/1/14
to Klaus Post, golan...@googlegroups.com
Include *hal.Resource is a must? If you want to publish a third-party
resource you cannot easily.
I suggest to use an API similar to:
https://github.com/mcuadros/go-jsonschema-generator/blob/master/example/simple.go

Regards
> --
> You received this message because you are subscribed to the Google Groups
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to golang-nuts...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Nicolas Vellon

unread,
Dec 1, 2014, 12:33:50 PM12/1/14
to Máximo Cuadros, Klaus Post, golan...@googlegroups.com
Thank you guys (specially @Klaus) for taking the time to looking the package and send your feedback.

I agree in most of what you said and I'll do changes or receive yours if you want to PR.... The only point I discuss is about design suggestions:

The "design approach" was to avoid struct composing. What @Klaus suggested (composing with hal.Resource) was my first try, but I quickly realized what @Máximo pointed:  3rd party struct would not be changed to be composed with hal.Resource. Event if I had control of the struct, I'd prefer having my json+hal encoding code decoupled from my "business" structs... that's when I added the HalEncoder interface, to give more flexibility to package users... does it make any sense to you?

A quick note about the package name: it was because I another GH repo named hal... 

Klaus Post

unread,
Dec 1, 2014, 2:19:26 PM12/1/14
to golan...@googlegroups.com, mcua...@gmail.com, klau...@gmail.com
Hi!

I didn't know that was a business requirement :)

Anyway, you can easily add both options. I rarely encounter cases where I don't have the model code in my control, so for me, if I was to use this as a library would be very annoyed that I had to implement this for each type - not to mention that I would need to keep code in sync with my model struct.

Hope you got some inspiration to move forward.

/Klaus

Nicolas Vellon

unread,
Dec 3, 2014, 12:05:06 AM12/3/14
to golan...@googlegroups.com
Updated the repo with some changes:

* New package name: https://github.com/nvellon/hal
* Return pointers from NewXxxx() when needed.
* Names in struct initialization.
* Added named types for better readability.
* Replaced Link struct with named types to avoid custom interface implementation.

Still couldn't get rid of the need of custom interface implementation for external structs. Them being composed with hal.Resource, means complications when trying to embed hal.Resources... But will give it another try later.

Thanks guys!
Reply all
Reply to author
Forward
0 new messages