|
Here's a realistic example: ChatGPT> Parse the album names and genres out of this json using Haskell's Aeson library and print them out in csv format:
{
"items": [
{
"track": {
"album": {
"total_tracks": 9,
"name": "playlist 1",
"genres": [
"Egg punk",
"Noise rock"
]
}
}
},
{
"track": {
"album": {
"total_tracks": 5,
"name": "playlist 2",
"genres": [
"NotEgg punk",
"NotNoise rock"
]
}
}
}
]
}
<shell-maker-end-of-prompt>
Here's the code to parse the JSON and print out the album names and genres in CSV format:
```haskell
{-# LANGUAGE DeriveGeneric #-}
import Data.Aeson
import Data.List (intercalate)
import GHC.Generics
data Track = Track { album :: Album }
deriving (Show, Generic)
data Album = Album { total_tracks :: Int, name :: String, genres :: [String] }
deriving (Show, Generic)
data Response = Response { items :: [Item] }
deriving (Show, Generic)
data Item = Item { track :: Track }
deriving (Show, Generic)
instance FromJSON Album
instance FromJSON Track
instance FromJSON Item
instance FromJSON Response
main :: IO ()
main = do
json <- readFile "example.json"
let parsed = decode json :: Maybe Response
case parsed of
Nothing -> putStrLn "Failed to parse JSON"
Just response -> mapM_ printAlbum $ items response
printAlbum :: Item -> IO ()
printAlbum item = do
let albumName = name . album . track $ item
albumGenres = intercalate ", " $ genres . album . track $ item
putStrLn $ albumName ++ "," ++ albumGenres
```
Assuming the JSON is stored in the file "example.json", running this program will output:
```
playlist 1,Egg punk, Noise rock
playlist 2,NotEgg punk, NotNoise rock
```
This is the album name and genres from each item in the "items" list of the JSON, separated by a comma.
ChatGPT> gpt1.hs:27:23: error:
• Couldn't match type ‘[Char]’
with ‘Data.ByteString.Lazy.Internal.ByteString’
Expected: Data.ByteString.Lazy.Internal.ByteString
Actual: String
• In the first argument of ‘decode’, namely ‘json’
In the expression: decode json :: Maybe Response
In an equation for ‘parsed’: parsed = decode json :: Maybe Response
|
27 | let parsed = decode json :: Maybe Response
|
<shell-maker-end-of-prompt>
The error message is indicating that there's a type mismatch between the `json` string and the expected `ByteString` type needed by the `decode` function.
To fix this, you can use the `Data.ByteString.Lazy.Char8` module to create a `ByteString` from the `json` string:
```haskell
import qualified Data.ByteString.Lazy.Char8 as BS
-- ...
main :: IO ()
main = do
json <- BS.readFile "example.json" -- use ByteString.readFile instead of readFile
let parsed = decode json :: Maybe Response
-- ...
```
With this change, the `json` string is read as a `ByteString` instead of a `String`, and the `decode` function should be able to parse it properly.
And it works fine: $ nix-shell -p "haskellPackages.ghcWithPackages (ps: with ps; [aeson])" --run "runhaskell gpt1.hs"
playlist 1,Egg punk, Noise rock
playlist 2,NotEgg punk, NotNoise rock
|
I mean, let's say you really do have to parse this format for something at work.
So you run it on a GB of similar data (meaning not literally specifically a GB, but well more than you can reasonably verify by hand).
Then what? How do you know it works fine, or if it obviously crashes, what to do next?