I have this work where I have to read a JSON from a file and generate instances of it based on its model. I'm using aeson to serialize the objects, but I'm having a huge problem dealing with randomness to produce new objects.
Produce a new JSON based on what I get from file is pretty straight forward:
{-# LANGUAGE OverloadedLists #-}
{-# LANGUAGE OverloadedStrings #-}
import qualified Data.ByteString.Lazy.Char8 as ByteString
import qualified Data.Aeson as Aeson
import qualified Data.Aeson.Types as Types
import qualified Data.Text
read :: String -> IO ()
read filePath = do
json <- readFile filePath
let Just parsedJSON =
Data.Aeson.decode $ ByteString.pack json :: Maybe Aeson.Object
let newJSON = fmap valueMapper parsedJSON
print $ Aeson.encode newJSON
valueMapper :: Types.Value -> Types.Value
valueMapper value =
case value of
Types.String _ -> Types.String "randomValue"
Types.Number _ -> Types.Number 0
Types.Object object -> Types.Object $ fmap valueMapper object
Types.Array array -> Types.Array $ fmap valueMapper array
My first attempt was to produce random values outside the IO. I used this function:
randomStr :: String
randomStr = take 10 $ randomRs ('a','z') $ unsafePerformIO newStdGen
Putting it on valueMapper
:
valueMapper :: Types.Value -> Types.Value
valueMapper value =
case value of
Types.String _ -> Types.String $ Data.Text.pack randomStr
Types.Number _ -> Types.Number 0
Types.Object object -> Types.Object $ fmap valueMapper object
Types.Array array -> Types.Array $ fmap valueMapper array
This "works", but all generated strings are the same, for every String
field.
After a little research, I found out that if I want to produce different values for each String
occurrence, I have to use the IO:
randomStr :: IO String
randomStr = replicateM 10 (randomRIO ('a', 'z'))
Now, I know that I have different strings for each call of randomStr
... But I also have a type mismatch. Aeson String
constructor to Value
takes a Data.Text
, but what I have is an IO String
. As far as I know, my strings can never come back from IO
.
I don't know if there is a way (hope so) to use the latest randomStr
to compose my new JSON object. I also don't know if my approach is a good one. I'm open to suggestions about how can I put this to work, in my or any other way (some tips on how to write better code would be awesome too).
Aucun commentaire:
Enregistrer un commentaire