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

Support JSONPath in error messages #1807

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

Gabriella439
Copy link

JSON error messages can optionally include the JSON path so that you get a nicer error like Error in $.foo.bar: rest of the message. The trick is to parse into an IResult instead of a Result since IResult includes a JSONPath.

This also updates the requre*JsonBody utilites to use these new IResult-based utilities, so anything that depends on them will automatically pick up improved error messages.

Before submitting your PR, check that you've:

After submitting your PR:

  • Update the Changelog.md file with a link to your PR
  • Check that CI passes (or if it fails, for reasons unrelated to your change, like CI timeouts)

JSON error messages can optionally include the JSON path so that you
get a nicer error like `Error in $.foo.bar: rest of the message`.
The trick is to parse into an `IResult` instead of a `Result` since
`IResult` includes a `JSONPath`.

This also updates the `requre*JsonBody` utilites to use these new
`IResult`-based utilities, so anything that depends on them will
automatically pick up improved error messages.
Comment on lines +127 to +130
eValue <- runConduit $ rawRequestBody .| runCatchC (sinkParser JP.value')
return $ case eValue of
Left e -> JT.IError [] $ show e
Right value -> JT.ifromJSON value
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see the symmetry with the parseInsecureJsonBody, but I must admit I'm curious about this implementation.

It seems like we have a two step process here - first piping the ConduitT _ ByteString _ () into a JSON parser to get an intermediate Value, and then calling ifromJSON on that value.

But eitherDecodeStrict works on lazy ByteString, and calls ifromJSON too:

-- | Like 'decodeStrict' but returns an error message when decoding fails.
eitherDecodeStrict :: (FromJSON a) => B.ByteString -> Either String a
eitherDecodeStrict =
  eitherFormatError . eitherDecodeStrictWith jsonEOF ifromJSON

If we did rawRequestBody .| sinkLazy, then we'd get a Lazy.ByteString, which we could provide to eitherDecodeStrict and that would give us the JSON path error, albeit pre-formatted in the String error message. But that's what we end up doing anyway, so it may not be too bad.

But I'm also hesitant to change the implementation of a core bit of this without understanding why it is the way it is.

@snoyberg do you have any thouughts on this? tl;dr: this implementation requires an aeson >= 2.1 bound, and the eitherDecodeStrict implementation would work for our current bounds.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think adding a strict lower requiring aeson 2 of any kind may be a problem, I know of at least a few companies out there that haven't been able to migrate over yet. Would it be possible to keep backwards compat with CPP?

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

Successfully merging this pull request may close these issues.

3 participants