go-json-experiment / json

Experimental implementation of a proposed v2 encoding/json package
BSD 3-Clause "New" or "Revised" License
341 stars 11 forks source link

better error message with semantic errors #35

Open elv-gilles opened 2 months ago

elv-gilles commented 2 months ago

I'm taking as example a field network_id of type uint64

NetworkId  uint64 `json:"network_id,omitempty"` 

and the following values entered mistakenly by a user:

The following errors are returned

with 'encoding/json':

In the 2 first cases, there's at least a small chance that a user could correct himself. In the third case, the user is returned an error that has no indication of where it originated (also a user does not necessarily know about Go types).

with 'json/v2':

The verbosity of the error message in increased, but the user is still returned a message that does not help finding what and where the problem is.

Test code is in config_errors/config_test.go.

why not returning the offending value and location of the error ?

Ideally, the error would also indicate the name of the field where the failure occurs and would become:

With the additional change that - if the json pointer (in SemanticErrror) is available - replace field 'network_id' with path '/x/y/network_id'.

Looking at the code :

additional question: why Hyrum-proof ?

What is the reason for returning an error message (pseudo) randomly prefixed in SemanticError ?

func (e *SemanticError) Error() string {
    var sb strings.Builder
    sb.WriteString(errorPrefix)

    // Hyrum-proof the error message by deliberately switching between
    // two equivalent renderings of the same error message.
    // The randomization is tied to the Hyrum-proofing already applied
    // on map iteration in Go.
    for phrase := range map[string]struct{}{"cannot": {}, "unable to": {}} {
        sb.WriteString(phrase)
        break // use whichever phrase we get in the first iteration
    }
    ...

POC / Proposal

I made some changes - limited to the 3 above cases - in this commit 6c0af11 of my json-experiment fork. With these changes these errors now show like this:

which, in my opinion - looks more useful though still a bit long.

Further removing Go value of type XX within JSON from the error string would make an even better error message:

What do you think ?

dsnet commented 2 months ago

Thanks for your thoughts. It's been on my TODO list to revamp how errors are populated and rendered. The current status quo isn't reflective of where we would like error reporting to get. What you proposed is fairly similar to what we would like it to eventually become.

why Hyrum-proof ?

This is precisely to provide us the ability to improve the error message in the future with less probability of breaking people who were depending on the error message being of a particular format today. While maintaining the Go stdlib, it was unfortunately common to rollback a CL because it altered the exact text of some error message, and some piece of code was depending on error string parsing to affect program logic.

We can always remove the Hyrum proofing, but not add it back. Once the error message is more stable, we can consider removing the deliberate randomization.

elv-gilles commented 2 months ago

ok, thanks for your answer.