Mittenchops
Mittenchops

Reputation: 19724

Easiest way to enter a JSON literal in Haskell ghci

I'm testing out some functions in ghci before I put them into a project, and I'm straining to find the simplest way to enter json literals in the ghci without a ton of boilerplate

For example, I'd like to try out:

myFuncThatTakesAJson

on inputs

x = {}
y = {"a": 1}

But when I try entering these:

import Text.JSON

Prelude> x = parseJSON "{}"
Prelude> y = parseJSON "{'a' : 1}"

I see errors like:

<interactive>:17:5: error:
    Variable not in scope: parseJSON :: [Char] -> t

y = fromJSON "{'a' : 1}"

<interactive>:20:5: error:
    Data constructor not in scope: FromJSON :: [Char] -> t

Is there any way to allow json objects to be entered as strings without defining full data types with custom FromJSON instances?

Upvotes: 1

Views: 318

Answers (1)

Alec
Alec

Reputation: 32319

There sure is! The type of a raw JSON value is Value. With that in mind, here's a couple of ways of constructing a Value in GHCi:

  • with parseJSON: since Value also has a FromJSON instance, you can use decode :: FromJSON a => ByteString -> Maybe a on it. Note that aeson is encouraging you to use ByteString instead of the inefficient default String. You can gloss over this detail by making string literals be overloaded by turning on -XOverloadedStrings:

    ghci> import Data.ByteString
    ghci> import Data.Aeson
    ghci> :set -XOverloadedStrings
    ghci> x = decode "{}" :: Maybe Value
    x :: Maybe Value
    ghci> y = decode "{\"a\" : 1}" :: Maybe Value    -- note: single quotes won't work
    y :: Maybe Value
    
  • with quasiquotes: you can also make use of the aesonQQ quasiquoter to get compile time JSON literals (this won't matter much in the REPL, beyond looking nicer, but in real code it means no actual parsing at runtime):

    ghci> import Data.Aeson.QQ.Simple
    ghci> :set -XQuasiQuotes
    ghci> x = [aesonQQ| {} |]
    x :: Value
    ghci> y = [aesonQQ| {"a" : 1} |]
    y :: Value
    

Upvotes: 3

Related Questions