How to parse JSON into existential type

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Baa
Reply | Threaded
Open this post in threaded view
|

How to parse JSON into existential type

Baa
Hello List!

In some of my JSONs I have part "list of any values", for example:

  [1, "hi", "false", 2.71]

To parse it I create type like:

  data RespItem = forall a. FromJSON a => RespItem {
    riItem :: [a] }

,-------------------------------------------------------------------
| btw, I try `(FromJSON a, Show a, Generic a) => ...` also but don't
| see any difference, so I'm not sure what is right constraints list.
`-------------------------------------------------------------------

And GHC does not allow to derive automatically with "deriving" Show
and Generic instances for existential types, as I see. So I write:

  instance Generic RespItem
  instance Show RespItem

Also this type `RespItem` in part of another one:

  data Resp = Resp {
    rHeadings :: [T.Text]
    , rRow    :: [RespItem]
    } deriving (Generic, Show)

Interesting is that now auto-`deriving` works! OK, but I need to
to instantiate `FromJSON` for RespItem because next step must be
`FromJSON` for Resp. So I'm trying:

  instance FromJSON RespItem where
    parseJSON ??? = ???

and here I get different errors, and absolutely don't understand how to
parse it, I get "ambiguous type error..." and so on (which is right,
sure).


===
Best regards, Paul
_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
Reply | Threaded
Open this post in threaded view
|

Re: How to parse JSON into existential type

David McBride
Rather than having an existential, which is difficult to work with at
the best of times, how about making RespItem into something concrete?
You could make your own data type to represent strings and arrays and
objects, etc, but you could also just use Value from aeson, since it
already exists and already has a FromJSON instance.

data Resp = Resp {
  rHeadings :: [T.Text],
  rRow :: [Data.Aeson.Value]
}

I couldn't get deriving Generic to work, but I've personally not had
too much trouble writing aeson instances manually.

instance FromJSON Resp where
  parseJSON = withObject "Resp" $ \v -> Resp <$> v .: "headings" <*> v .: "rows"

There is also an aeson-lens package that can make parsing json easy,
if you are into lenses.


On Tue, Aug 29, 2017 at 8:36 AM, Baa <[hidden email]> wrote:

> Hello List!
>
> In some of my JSONs I have part "list of any values", for example:
>
>   [1, "hi", "false", 2.71]
>
> To parse it I create type like:
>
>   data RespItem = forall a. FromJSON a => RespItem {
>     riItem :: [a] }
>
> ,-------------------------------------------------------------------
> | btw, I try `(FromJSON a, Show a, Generic a) => ...` also but don't
> | see any difference, so I'm not sure what is right constraints list.
> `-------------------------------------------------------------------
>
> And GHC does not allow to derive automatically with "deriving" Show
> and Generic instances for existential types, as I see. So I write:
>
>   instance Generic RespItem
>   instance Show RespItem
>
> Also this type `RespItem` in part of another one:
>
>   data Resp = Resp {
>     rHeadings :: [T.Text]
>     , rRow    :: [RespItem]
>     } deriving (Generic, Show)
>
> Interesting is that now auto-`deriving` works! OK, but I need to
> to instantiate `FromJSON` for RespItem because next step must be
> `FromJSON` for Resp. So I'm trying:
>
>   instance FromJSON RespItem where
>     parseJSON ??? = ???
>
> and here I get different errors, and absolutely don't understand how to
> parse it, I get "ambiguous type error..." and so on (which is right,
> sure).
>
>
> ===
> Best regards, Paul
> _______________________________________________
> Beginners mailing list
> [hidden email]
> http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners
Baa
Reply | Threaded
Open this post in threaded view
|

Re: How to parse JSON into existential type

Baa
Ohh, right, there is `Value`!! Thank you David for good idea!

> Rather than having an existential, which is difficult to work with at
> the best of times, how about making RespItem into something concrete?
> You could make your own data type to represent strings and arrays and
> objects, etc, but you could also just use Value from aeson, since it
> already exists and already has a FromJSON instance.
>
> data Resp = Resp {
>   rHeadings :: [T.Text],
>   rRow :: [Data.Aeson.Value]
> }
>
> I couldn't get deriving Generic to work, but I've personally not had
> too much trouble writing aeson instances manually.
>
> instance FromJSON Resp where
>   parseJSON = withObject "Resp" $ \v -> Resp <$> v .: "headings" <*>
> v .: "rows"
>
> There is also an aeson-lens package that can make parsing json easy,
> if you are into lenses.
>
>
> On Tue, Aug 29, 2017 at 8:36 AM, Baa <[hidden email]> wrote:
> > Hello List!
> >
> > In some of my JSONs I have part "list of any values", for example:
> >
> >   [1, "hi", "false", 2.71]
> >
> > To parse it I create type like:
> >
> >   data RespItem = forall a. FromJSON a => RespItem {
> >     riItem :: [a] }
> >
> > ,-------------------------------------------------------------------
> > | btw, I try `(FromJSON a, Show a, Generic a) => ...` also but don't
> > | see any difference, so I'm not sure what is right constraints
> > list.
> > `-------------------------------------------------------------------
> >
> > And GHC does not allow to derive automatically with "deriving" Show
> > and Generic instances for existential types, as I see. So I write:
> >
> >   instance Generic RespItem
> >   instance Show RespItem
> >
> > Also this type `RespItem` in part of another one:
> >
> >   data Resp = Resp {
> >     rHeadings :: [T.Text]
> >     , rRow    :: [RespItem]
> >     } deriving (Generic, Show)
> >
> > Interesting is that now auto-`deriving` works! OK, but I need to
> > to instantiate `FromJSON` for RespItem because next step must be
> > `FromJSON` for Resp. So I'm trying:
> >
> >   instance FromJSON RespItem where
> >     parseJSON ??? = ???
> >
> > and here I get different errors, and absolutely don't understand
> > how to parse it, I get "ambiguous type error..." and so on (which
> > is right, sure).
> >
> >
> > ===
> > Best regards, Paul
> > _______________________________________________
> > Beginners mailing list
> > [hidden email]
> > http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners 
> _______________________________________________
> Beginners mailing list
> [hidden email]
> http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners

_______________________________________________
Beginners mailing list
[hidden email]
http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners