Title here
Summary here
import Data.String
import Data.List
import Data.Maybe
import System.File
import Language.JSON
-- We'll use these two records to demonstrate encoding and
-- decoding of custom types below.
record Response1 where
constructor MkResponse1
page : Int
fruits : List String
record Response2 where
constructor MkResponse2
page : Int
fruits : List String
main : IO ()
main = do
-- First we'll look at encoding basic data types to
-- JSON strings. Here are some examples for atomic
-- values.
putStrLn $ show $ encode True
putStrLn $ show $ encode 1
putStrLn $ show $ encode 2.34
putStrLn $ show $ encode "gopher"
-- And here are some for lists and dictionaries, which encode
-- to JSON arrays and objects as you'd expect.
let slcD = ["apple", "peach", "pear"]
putStrLn $ show $ encode slcD
let mapD = [("apple", 5), ("lettuce", 7)]
putStrLn $ show $ encode mapD
-- The JSON package can automatically encode your
-- custom data types. It will only include exported
-- fields in the encoded output and will by default
-- use those names as the JSON keys.
let res1D = MkResponse1 1 ["apple", "peach", "pear"]
putStrLn $ show $ encode res1D
-- Now let's look at decoding JSON data into Idris
-- values. Here's an example for a generic data
-- structure.
let byt = "{\"num\":6.13,\"strs\":[\"a\",\"b\"]}"
-- We need to provide a type where the JSON
-- package can put the decoded data. This
-- `Maybe (List (String, JSON))` will hold a dictionary of strings
-- to arbitrary data types.
case decode byt of
Just (JObject dat) => do
putStrLn $ show dat
-- In order to use the values in the decoded map,
-- we'll need to convert them to their appropriate type.
-- For example here we convert the value in `num` to
-- the expected `Double` type.
case lookup "num" dat of
Just (JNumber num) => putStrLn $ show num
_ => putStrLn "Failed to find 'num'"
-- Accessing nested data requires a series of
-- pattern matches.
case lookup "strs" dat of
Just (JArray strs) =>
case head' strs of
Just (JString str1) => putStrLn str1
_ -> putStrLn "Failed to get first string"
_ -> putStrLn "Failed to find 'strs'"
_ -> putStrLn "Failed to parse JSON"
-- We can also decode JSON into custom data types.
-- This has the advantages of adding additional
-- type-safety to our programs and eliminating the
-- need for type assertions when accessing the decoded
-- data.
let str = "{\"page\": 1, \"fruits\": [\"apple\", \"peach\"]}"
case decode str of
Just (JObject obj) =>
case fromJSON obj of
Just res => do
putStrLn $ show res
putStrLn $ show $ head' (fruits res)
Nothing -> putStrLn "Failed to parse into Response2"
_ -> putStrLn "Failed to parse JSON"
-- In the examples above we always used strings as
-- intermediates between the data and JSON representation.
-- We can also stream JSON encodings directly to files or
-- even network connections.
let d = [("apple", 5), ("lettuce", 7)]
Right () <- writeFile "output.json" (show $ encode d)
| Left err => putStrLn $ "Error writing file: " ++ show err
pure ()
This Idris code demonstrates JSON encoding and decoding, similar to the Go example. However, there are some differences due to Idris’s features and limitations:
record
instead of struct
for defining custom types.Language.JSON
module, which provides encode
and decode
functions.json.NewEncoder
, so file writing is done more directly.Note that Idris’s standard library might not have all the JSON functionality that Go’s encoding/json
package provides. In a real-world scenario, you might need to use or create additional libraries for more advanced JSON handling.