Question

I'm fairly new to Haskell, so I meant be missing something simple. Right now, I'm just trying to read in some JSON from stdin and get the AST back as a proof of concept.

module JSONStuff where

import qualified Data.Aeson as JSON
import qualified Data.ByteString.Lazy.Char8 as Char

main :: IO ()
main = do
    input <- Char.getContents
    case JSON.eitherDecode input of
        Left err -> putStrLn $ "Bad JSON: " ++ err
        Right value -> do
            putStrLn "Got:"
            putStrLn value

I have this JSON fragment (which JSONLint says is ok):

{
  "foo": 123
}

When I the program with that input, I get:

$ cat examples/object.json | runhaskell Main.hs
Bad JSON: when expecting a String, encountered Object instead

When I test on a file that's and empty array, it says it "encountered Array instead".

So I'm guessing I'm missing some kind of conversion step in here, or I'm reading from stdin incorrectly. What do you think?

Was it helpful?

Solution

The problem is this line:

putStrLn value

Since the type of putStrLn is String -> IO (), the type of value is inferred as String, so the FromJSON instance for strings will be used, which will only decode strings, since that's what the type can handle. To decode something else, you need a different type for value.

Try

print (value :: JSON.Object)

if you expect an object, or

print (value :: JSON.Value)

if any JSON value is acceptable.

Note the use of print instead of putStrLn. print accepts any type with a Show instance, so unlike putStrLn it does not force its argument to be a string. Also note that print value without the type annotation would not work in this example, as there would not be enough information for the compiler to deduce which type value should have, and therefore which Show and FromJSON instances to use.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top