purescript-contrib/purescript-argonaut-codecs

Add example to readme of automatic decoding into simple record types

chexxor opened this issue · 5 comments

I heard this library now has automatic decoding into a plain record type, like simple-json is known for.
#46

It would be nice to see in the README that this library has this functionality, and to see an example of how to use it.

I guess it would be used something like this:

testDecode :: Maybe { a :: Int, b :: String }
testDecode = decodeJson """ { a: 123, b: "xyz" } """

Yea! I think the README could use this -- and a lot more, too, to help folks understand how to use the library. Documentation is pretty sparse right now. I've added the 'help wanted' label as this would be a great first issue for someone familiar with the library or with similar ones like Aeson.

If there's no luck, ping me and I'll make sure to come back to this and see if I can make time to add some of these docs as well.

To whomever updates the readme for this, it would also be nice to note that this library is now closer to Aeson API rather than Scala's Argonaut. I haven't used either of those other libraries but it's what I gather from reading the discussion so far. Looks like this library started moving in the Aeson direction a few years ago, actually.

This is what I wrote before coming to this issue:

newtype PersonInfo = PersonInfo { name :: String, age :: Int }

instance encodeJsonPersonInfo :: EncodeJson PersonInfo where
  encodeJson (PersonInfo rec) =
    "name" := rec.name ~>
    "age" := rec.age ~>
    jsonEmptyObject

instance decodeJsonPersonInfo :: DecodeJson PersonInfo where
  decodeJson json = PersonInfo <$> decodeJson
    x <- decodeJson json
    name <- x .: "name"
    age <- x .: "age"
    pure $ PersonInfo {name, age}

This is what I wrote after I read through Alex's comment above:

newtype PersonInfo = PersonInfo { name :: String, age :: Int }

instance encodeJsonPersonInfo :: EncodeJson PersonInfo where
  encodeJson (PersonInfo rec) = encodeJson rec

instance decodeJsonPersonInfo :: DecodeJson PersonInfo where
  decodeJson json = PersonInfo <$> decodeJson json

That really made a difference.

@JordanMartinez I think you can get away with

newtype PersonInfo = PersonInfo { name :: String, age :: Int }

derive newtype instance encodePersonInfo :: EncodeJson PersonInfo
derive newtype instance decodeJsonPersonInfo :: DecodeJson PersonInfo

as well, because it will defer to the underlying instance. In a repl:

> stringify (encodeJson (PersonInfo { name: "Tim", age: 40 }))
"{\"name\":\"Tim\",\"age\":40}"

Oh, right! Forgot about that newtype, haha.