jsonhaskelldeserializationaeson

Deserializing JSON file with aeson in Haskell


I'm new in Haskell. Currently I'm working on a SQL project and I got stuck on deserializing JSON file contents. I'm getting some cursed error and I don't know how to fix it.

This is my JSON file:

{
"Table":"flags",
"Columns":[
  {"Name":"flag", "ColumnType":"StringType"},
  {"Name":"value", "ColumnType":"BoolType"}],
"Rows":[
  [{"Value":"StringValue a"}, {"Value":"BoolValue True"}],
  [{"Value":"StringValue b"}, {"Value":"BoolValue True"}],
  [{"Value":"StringValue b"}, {"Value":"NullValue"}],
  [{"Value":"StringValue b"}, {"Value":"BoolValue False"}]
  ]
}

This is my Haskell code:

data FromJSONColumn = FromJSONColumn {
  deserializedName :: String,
  deserializedDataType :: String
  } deriving (Show, Eq, Generic)

instance FromJSON FromJSONColumn where

parseJSON (Object v) =
  FromJSONColumn <$> v .: "Name"
  <*> v .: "ColumnType"

parseJSON _ = mzero

This is the error I get:

JSONExample.hs:17:27-32: error:
    • Couldn't match type ‘[Char]’ with ‘Key’
      Expected: Key
        Actual: String
    • In the second argument of ‘(.:)’, namely ‘"Name"’
      In the second argument of ‘(<$>)’, namely ‘v .: "Name"’
      In the first argument of ‘(<*>)’, namely
        ‘FromJSONColumn <$> v .: "Name"’
   |
17 |   FromJSONColumn <$> v .: "Name"
   |                           ^^^^^^

JSONExample.hs:18:12-23: error:
    • Couldn't match type ‘[Char]’ with ‘Key’
      Expected: Key
        Actual: String
    • In the second argument of ‘(.:)’, namely ‘"ColumnType"’
      In the second argument of ‘(<*>)’, namely ‘v .: "ColumnType"’
      In the expression:
        FromJSONColumn <$> v .: "Name" <*> v .: "ColumnType"
   |
18 |   <*> v .: "ColumnType"
   |            ^^^^^^^^^^^^

Could somebody explain how to write instances for such files (files that contain tables) ? How should I do it? I'm truly lost.

P.S. This is the data types I'm working with:

data ColumnType
  = IntegerType
  | StringType
  | BoolType
  deriving (Show, Eq)

data Column = Column String ColumnType
  deriving (Show, Eq)

data Value
  = IntegerValue Integer
  | StringValue String
  | BoolValue Bool
  | NullValue
  deriving (Show, Eq)

type Row = [Value]

data DataFrame = DataFrame [Column] [Row]
  deriving (Show, Eq)

Solution

  • The second argument to the .: operator should be of type Key, but you're passing in a [Char] (also known as String). Try one of the following to convert them into a Key:

    1. Enable the OverloadedStrings extension. I.e., add {-# LANGUAGE OverloadedStrings #-} to the top of the source code.

    2. Instead of "Name", try fromString "Name". Likewise, instead of "ColumnType", try fromString "ColumnType". fromString should be imported from the Data.Aeson.Key module. This actually does the same thing as the first option, but the OverloadedStrings extension does this for you.