Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to readJSON for completely empty input? #66

Closed
cah6 opened this issue Sep 26, 2019 · 3 comments
Closed

How to readJSON for completely empty input? #66

cah6 opened this issue Sep 26, 2019 · 3 comments

Comments

@cah6
Copy link

cah6 commented Sep 26, 2019

Hey there,

I'm using Affjax to execute requests, defining the response format as String, and then using readJSON to parse the response into some type defined by the caller. I have a request, though, where the success response is nothing, i.e. completely empty. I tried defining the a in readJSON to be String, Maybe String, Nullable String, Foreign, etc but it all returns a parse error on the readJSON call. What I think I need is an instance for ReadForeign Unit that looks like:

instance readForeignUnit :: ReadForeign Unit where
  readImpl = pure unit

such that callers that expect the response to be completely empty can define that in the type and have a useless result be returned back in that slot. Can you foresee any issues with this or do you have any other suggestions for what to do here?

@justinwoo
Copy link
Owner

Unit is not meant to have some JSON representation or anything. It seems like what you should be doing is defining a different function to call upstream such that the response bodies aren't automatically parsed.

Regardless what you use, the initial JSON parsing will fail when dealing with the invalid JSON string. ReadForeign really only deals with how to deal with actual Foreign values being decoded, not the actual parsing of the JSON string.

@justinwoo
Copy link
Owner

justinwoo commented Sep 27, 2019

You don't have to take my word for it, look at how the readJSON methods work by first calling parseJSON, which is a separate function:

-- | Read a JSON string to a type `a` while returning a `MultipleErrors` if the
-- | parsing failed.
readJSON :: forall a
. ReadForeign a
=> String
-> E a
readJSON = runExcept <<< (readImpl <=< parseJSON)
-- | Read a JSON string to a type `a` using `F a`. Useful with record types.
readJSON' :: forall a
. ReadForeign a
=> String
-> F a
readJSON' = readImpl <=< parseJSON

parseJSON :: String -> F Foreign
parseJSON
= ExceptT
<<< Identity
<<< lmap (pure <<< ForeignError <<< message)
<<< runPure
<<< try
<<< EU.runEffectFn1 _parseJSON
where
-- Nate Faubion: "It uses unsafePerformEffect because that’s the only way to catch exceptions and still use the builtin json decoder"
runPure = unsafePerformEffect

@cah6
Copy link
Author

cah6 commented Oct 8, 2019

Ack, sorry for the delay here. You're right, of course; when I made this ticket I had forgotten that a completely blank input is indeed invalid JSON.

For anybody else that might stumble on this: what we ended up doing was parameterizing our request method on a "how to handle the response" input (more or less of type String -> E a) and giving it readJSON in the usual case but giving it const (Right unit) in the case where the expected response is unit.

Closing this, thank you!

@cah6 cah6 closed this as completed Oct 8, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants