# \[squeal-posgresql\] Decoding JSONB to Aeson.Value

**URL:** <https://discourse.haskell.org/t/squeal-posgresql-decoding-jsonb-to-aeson-value/10303>\
**Category:** Learn\
**Created:** [September 8, 2024, 7:53am UTC](https://discourse.haskell.org/t/squeal-posgresql-decoding-jsonb-to-aeson-value/10303 "2024-09-08T07:53:57Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![magthe](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/magthe/32/1362_2.png) [@magthe](https://discourse.haskell.org/u/magthe)\
**Post date:** [September 8, 2024, 7:53am UTC](https://discourse.haskell.org/t/squeal-posgresql-decoding-jsonb-to-aeson-value/10303/1 "2024-09-08T07:53:57Z")

</div>

I have a query with the following type

```haskell
sql :: Query '[] with MySchema '['NotNull 'PGint4] '["id" ::: 'NotNull 'PGint4, "vals" ::: 'NotNull 'PGjsonb]

```

that I then want to turn into a `Statement`

```haskell
getValues :: Statement MySchema Int32 (Int32, Aeson.Value)
getValues = Query encode decode sql
  where
    encode = (\x -> x) .* nilParams
    decode = (,) <$> #id <*> #vals

```

This gives me the following error though

```haskell
* Couldn't match type `PGjsonb' with `PGjson'
    arising from the overloaded label `#vals'
* In the second argument of `(<*>)', namely `#vals'
  In the expression: (,) <$> #id <*> #vals
  In an equation for `decode': decode = (,) <$> #id <*> #vals

```

which confuses me. The schema says the field is `PGjsonb`, the query typechecks and the value is `PGjsonb`, so where does `PGjson` come in? How do I convert a `PGjsonb` field to an `Aeson.Value`? I’m clearly missing something here, but what?

(I originally posted this question [here](https://github.com/morphismtech/squeal/discussions/357), but thought I’d widen the audience a bit.)

---

<div class="post-metadata">

**Author:** ![MangoIV](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/mangoiv/32/3519_2.png) [@MangoIV](https://discourse.haskell.org/u/MangoIV)\
**Post date:** [September 8, 2024, 10:21am UTC](https://discourse.haskell.org/t/squeal-posgresql-decoding-jsonb-to-aeson-value/10303/2 "2024-09-08T10:21:24Z")

</div>

I think this is not quite enough context to properly trouble shoot the issue but my hunch is that a fundep (or type family, for that matter) associates PGjson with Aeson and you would need to wrap `Value` in a newtype wrapper s.t. it works with the overloaded labels.

---

<div class="post-metadata">

**Author:** ![magthe](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/magthe/32/1362_2.png) [@magthe](https://discourse.haskell.org/u/magthe)\
**Post date:** [September 8, 2024, 10:38am UTC](https://discourse.haskell.org/t/squeal-posgresql-decoding-jsonb-to-aeson-value/10303/3 "2024-09-08T10:38:55Z")

</div>

Hmm, so would that be necessary to make my own type (something implementing `ToJSON`/`FromJSON`) be required to make it work with `JSONB` too?

I’ll be happy to provide a more complete context if you think it’ll help.

---

<div class="post-metadata">

**Author:** ![MangoIV](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/mangoiv/32/3519_2.png) [@MangoIV](https://discourse.haskell.org/u/MangoIV)\
**Post date:** [September 8, 2024, 11:41am UTC](https://discourse.haskell.org/t/squeal-posgresql-decoding-jsonb-to-aeson-value/10303/4 "2024-09-08T11:41:06Z")

</div>

As I said, I would try a newtype wrapper for Value. Call it BValue?

---

<div class="post-metadata">

**Author:** ![magthe](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/magthe/32/1362_2.png) [@magthe](https://discourse.haskell.org/u/magthe)\
**Post date:** [September 8, 2024, 1:16pm UTC](https://discourse.haskell.org/t/squeal-posgresql-decoding-jsonb-to-aeson-value/10303/5 "2024-09-08T13:16:11Z")

</div>

Ah, doing that made me go look at `FromPG`, which in turn lead me to the newtypes `Json` and `Jsonb`. So if I change the type of `getValues` to

```haskell
getValues :: Statement MySchema Int32 (Int32, Jsonb Aeson.Value)

```

then everything typechecks successfully. I just have to use `getJsonb` to extract the actual `Value`.

If I want to avoid having to deal with the `Jsonb` wrapper outside of `getValues` I can modify the decoder, thus I end up with

```haskell
getValues :: Statement MySchema Int32 (Int32, Aeson.Value)
getValues = Query encode decode sql
  where
    encode = (\x -> x) .* nilParams
    decode = mkResult <$> #id <*> #vals
    mkResult id_ vals = (id_, getJsonb vals)

```

---

<div class="post-metadata">

**Author:** ![MangoIV](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/mangoiv/32/3519_2.png) [@MangoIV](https://discourse.haskell.org/u/MangoIV)\
**Post date:** [September 8, 2024, 3:04pm UTC](https://discourse.haskell.org/t/squeal-posgresql-decoding-jsonb-to-aeson-value/10303/6 "2024-09-08T15:04:57Z")

</div>

ah yes, that’s what I expected 🙂
