Json in PureScript

Our first program will demonstrate how to work with JSON data in PureScript. Here’s the full source code:

module Main where

import Prelude

import Data.Argonaut.Core (Json, fromArray, fromNumber, fromObject, fromString, stringify)
import Data.Argonaut.Decode (class DecodeJson, decodeJson)
import Data.Argonaut.Encode (class EncodeJson, encodeJson)
import Data.Either (Either(..))
import Data.Map as Map
import Data.Maybe (Maybe(..))
import Effect (Effect)
import Effect.Console (log)
import Foreign.Object as FO

-- Define custom data types
type Response1 = 
  { page :: Int
  , fruits :: Array String
  }

newtype Response2 = Response2
  { page :: Int
  , fruits :: Array String
  }

-- Define instances for JSON encoding and decoding
instance encodeJsonResponse2 :: EncodeJson Response2 where
  encodeJson (Response2 r) = encodeJson
    { page: r.page
    , fruits: r.fruits
    }

instance decodeJsonResponse2 :: DecodeJson Response2 where
  decodeJson json = do
    obj <- decodeJson json
    page <- obj .: "page"
    fruits <- obj .: "fruits"
    pure $ Response2 { page, fruits }

main :: Effect Unit
main = do
  -- Encoding basic data types to JSON
  log $ stringify $ encodeJson true
  log $ stringify $ encodeJson 1
  log $ stringify $ encodeJson 2.34
  log $ stringify $ encodeJson "gopher"

  -- Encoding arrays and objects
  log $ stringify $ encodeJson ["apple", "peach", "pear"]
  log $ stringify $ encodeJson $ FO.fromFoldable [Tuple "apple" 5, Tuple "lettuce" 7]

  -- Encoding custom data types
  let res1 = { page: 1, fruits: ["apple", "peach", "pear"] }
  log $ stringify $ encodeJson res1

  let res2 = Response2 { page: 1, fruits: ["apple", "peach", "pear"] }
  log $ stringify $ encodeJson res2

  -- Decoding JSON data
  let jsonStr = """{"num":6.13,"strs":["a","b"]}"""
  case decodeJson jsonStr of
    Left err -> log $ "Failed to parse JSON: " <> show err
    Right (obj :: FO.Object Json) -> do
      log $ "Parsed object: " <> show obj
      case FO.lookup "num" obj of
        Just num -> log $ "num: " <> stringify num
        Nothing -> log "num not found"
      case FO.lookup "strs" obj of
        Just (arr :: Json) -> case fromArray arr of
          Just strArr -> case strArr !! 0 of
            Just str -> log $ "First string: " <> stringify str
            Nothing -> log "Empty array"
          Nothing -> log "Not an array"
        Nothing -> log "strs not found"

  -- Decoding into custom data types
  let jsonStr2 = """{"page": 1, "fruits": ["apple", "peach"]}"""
  case decodeJson jsonStr2 of
    Left err -> log $ "Failed to parse JSON: " <> show err
    Right (res :: Response2) -> do
      let (Response2 r) = res
      log $ "Parsed Response2: " <> show r
      log $ "First fruit: " <> show (r.fruits !! 0)

  -- Encoding directly to console output
  log $ stringify $ encodeJson $ FO.fromFoldable [Tuple "apple" 5, Tuple "lettuce" 7]

This program demonstrates how to work with JSON in PureScript:

  1. We import necessary modules for JSON encoding/decoding and other utilities.

  2. We define custom data types Response1 and Response2, similar to structs in other languages.

  3. We implement EncodeJson and DecodeJson instances for Response2 to allow custom JSON encoding and decoding.

  4. In the main function, we demonstrate:

    • Encoding basic data types, arrays, and objects to JSON.
    • Encoding custom data types to JSON.
    • Decoding JSON strings into PureScript data structures.
    • Decoding JSON into custom data types.
    • Encoding JSON directly to console output.
  5. We use stringify to convert JSON values to strings for output.

  6. For decoding, we use pattern matching with case expressions to handle potential errors and extract values.

  7. We demonstrate how to access nested data in decoded JSON objects.

To run this program, you would typically compile it with the PureScript compiler and then run it with Node.js. The exact commands may vary depending on your project setup, but it might look something like this:

$ pulp build
$ node output/Main/index.js

This example covers the basics of JSON handling in PureScript. For more advanced usage, you may want to refer to the documentation of the purescript-argonaut-core and purescript-argonaut-codecs libraries.