Picklers for de/serialising Generic data types to and from query strings

Latest on Hackage:0.2.0

This package is not currently in any snapshots. If you're interested in using it, we recommend adding it to Stackage Nightly. Doing so will make builds more reliable, and allow stackage.org to host generated Haddocks.

OtherLicense licensed by Brendan Hay
Maintained by Brendan Hay


Build Status

Table of Contents





Common Instances


No default instance for IsQuery a => IsQuery [a] is specified since there are a number of possible implementations. To that end, two pickling combinators are supplied:


A query string of the format ?key=Saab,Audi,Holden can be derived using qpList as follows:

instance IsQuery a => IsQuery [a] where
    queryPickler = qpList queryPickler


Alternatively, a query string of the format key.1=Saab&key.2=Audi&key.3=Holden can be derived using the qpOrdinalList combinator:

instance IsQuery a => IsQuery [a] where
    queryPickler = qpOrdinalList queryPickler

Ordering is preserved in both cases, although qpOrdinalList would preserve the order if the querystring was reshuffled.


IsQuery instances for Maybe a and Either a b are not supplied due to ambiguous semantics, take the following example:

instance IsQuery a => IsQuery (Maybe a) where
    queryPickler = qpOption queryPickler

instance (IsQuery a, IsQuery b) => IsQuery (Either a b) where
    queryPickler = queryPickler `qpEither` queryPickler

data A = A { aInt1 :: Int, aInt2 :: Int } deriving (Show, Generic)
data B = B { bA :: Maybe A } deriving (Show, Generic)
data C = C { cB :: B } deriving (Show, Generic)
data D = D { dAInt :: Either A Int } deriving (Show, Generic)

instance IsQuery A
instance IsQuery B
instance IsQuery C
instance IsQuery D

let c = C $ B Nothing
let d = D . Left $ A 1 2
let e = D $ Right 3

Running toQuery / fromQuery on the example bindings yields:

λ: toQuery c

λ: fromQuery (toQuery c) :: Either String C
Left "qpElem: non-locatable - B - List []"

λ: toQuery d

λ: fromQuery (toQuery d) :: Either String D
Right (D {dAInt = Left (A {aInt1 = 1, aInt2 = 2})})

λ: toQuery e

λ: fromQuery (toQuery e) :: Either String D
Right (D {dAInt = Right 3})

If data type B has a second non-optional field, the fromQuery deserialisation of binding c will succeed.

This is due to the overly simple underlying rose tree used as the intermediate data structure for query transforms. Something that will hopefully be fixed in a future release.

It is left up to the consumer of the library to decide best how to handle this case. I apologies if it forces anyone to use orphaned instances.


Due to the dependency on GHC.Generics a version of base 4.6 or higher is required.


For any problems, comments or feedback please create an issue here on GitHub.


querystring-pickle is released under the Mozilla Public License Version 2.0

Depends on 3 packages:
Used by 1 package:
comments powered byDisqus