Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parsing partial json objects with aeson in haskell

I am making a fairly simple CRUD web service in Haskell with Warp (and possibly Scotty) and acid-state.

In acid-state I store User records in a Data.Map (as per this example). I know that those records will always be complete upon creation, so I don't need to qualify with a lot of MaybeS. However, when updating a User, the client may choose to send a partial json object, with just some of the fields populated.

What would be the idiomatic way to represent this? Should I have one data declaration, FullUser, without MaybeS and one exactly the same with MaybeS in front of all optional keys, PartialUser, and let aeson automatically derive encode and decode for the latter, finally writing my own update function of the type :: FullUser -> PartialUser -> FullUser?

It would not be much much code, but it feels slightly ugly and like it violates DRY a bit. It should be such a common task in a web server, so perhaps it has already been solved generically (possibly with TH)?

I realize that I could just store the json string and always check for missing keys, making it slightly clumsier but more future proof for schema changes, but I would still like to know how I would do it in a "type safe" way.

EDIT: Or perhaps I should only have the FullUser and use aeson-lens to write a simple update function from a FullUser and a json string?

like image 680
Gurgeh Avatar asked Mar 04 '13 19:03

Gurgeh


1 Answers

Idiomatic Haskell is in doing as much static checking as possible. You should always approach your problem from a perspective of whether it is possible to replace dynamic checks with static ones. That's essentially what makes the following statement about Haskell quite close to reality: "If it compiles, it works". So definitely a "No" to working with plain JSON.

Your solution with FullUser and PartialUser is correct. Although I would suggest to take a different naming approach: User and UserJSON - this way you get a quite descriptive and reasonable meaning.

There is however a small problem with Aeson: the generated instances don't yet support parsing missing fields (please, vote on the issue). So you'll have to define the instances manually.

like image 191
Nikita Volkov Avatar answered Sep 22 '22 12:09

Nikita Volkov