On Tue, 19 Nov 2013 23:22:30 GMT, Mathias LANG wrote:

Hello all,
I started using vibe.d to build a REST API. I really love it !

I want to build a REST API.
I've seen vibe.http.rest and it's really good, but it seems to be lacking / forbidding a feature which I absolutely need: a way to handle [de]serialization.
(At least that's what https://github.com/rejectedsoftware/vibe.d/blob/master/examples/rest/source/app.d#L90 let me to believe)

The comment is not entirely correct anymore. The latest 0.7.18 betas support @name("somename"), @ignore, @optional and @byName attributes to customize how fields are (de-)serialized. However, it's still not possible to customize the serializer type that is used for the REST interface.

1) The main reason is that I would like to provide different media (ContentType) to people. So far, XML, JSON, HTML.
2) I'll also use ContentType over the URL-way for versioning (I'm aware of it's drawbacks).
3) And of course, I'd like to take full advantages of it by using objects / structs in the client, not return a string that I have to pass to another function.

So it looks like two additions to the REST system would be necessary: Allow to specify the serializer (JSON/XML/...) that is used, and allow to specify a custom suffix for each URL (".json"/".xml"/...). Then I'd imagine this to work in that scenario:

router.registerRestInterface!JsonStringSerializer(..., ".json");
router.registerRestInterface!XMLStringSerializer(..., ".xml");
router.registerRestInterface!HTMLStringSerializer(..., ".html");

Of course, the XML and HTML serializers would also have to be written, but that's trivial.

One thing to think about is how query parameters will be handled in this case. Currently all primitive types are directly converted to string (e.g. 2.5 gets param=2.5) and complex parameters get serialized to JSON (e.g. SomeStruct(2.5, "hello") might get param={"field1":2.5,"field2":"hello"}). XML or HTML might be less practical here. But JSON isn't optimal either, so maybe there is something entirely different that could be used here instead.

What I tried so far was mostly based on @before / @after attributes:

  • @before: handles the authen (and set others parameters based on the header, like the version), works like a charm;
  • @after: I tried to use it to set the format, but I need to return something (for 3), and it WILL be serialized. If I just write to HTTPServerResponse, my data get duplicated, so I needed to tell the framework how to do it. I first override toString(), which in turns called a delegate (toJson, toHtml, toXML), but no luck with that (doesn't get called?). I also thought of implementing a custom Json object, but it's a struct, so no inheritance, and that's really hacky.

Since the @before/@after feature is quite new, I didn't yet have the chance to actually try it out, so I'll defer an answer to later or to @Dicebot (who implemented it).

So the only solution I see so far is to implement the interface in the client only (I'll use JSON only for D), and implement the server without vibe.http.rest, only using plain URLRouter and stuff.

Did I missed a point ? Is there any plan to support custom [de]serialization sooner or later ?

I'm planning to rework the REST interface code a bit so that the MethodStyle is passed as a template parameter instead of as a runtime parameter (this would allow to shift a great amount of work from runtime to compile time and thus improve performance). I guess in that process it will be easy to also make the serializer a template argument. But I can't give an exact time schedule for this, yet.