-
Notifications
You must be signed in to change notification settings - Fork 18
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
Introduce jsontext.RawToken API for better number parsing #158
base: master
Are you sure you want to change the base?
Conversation
This is consistent with int overflow and json v1
These can be reused in jsontext. Note that jsonwire.ParseFloat now returns inf for overflow. But this should not impact user-visible behavior, because we don't set value when overflow.
Decoder now returns RawToken instead of Token. RawToken exposes a new set of methods: ParseFloat(bits int) (float64, error) ParseInt(bits int) (int64, error) ParseUint(bits int) (uint64, error) They reuses the same logic of arshalers, intended to offers Decoder user a more efficient and convenient way to parse numbers. Compared with the original Token.Float, these methods properly return errors for overflow, etc. Compared with strconv, these methods may take advantage of the fact that json number has simpler syntax than Go. Compared with json.UnmarshalDecode, these methods avoids the cost of arshaler lookup and reflection. New jsontext.Raw and Token.Raw func are added to convert between RawToken and Token. The original Float, Int, Uint methods now only support the case where the Token is created by the correspond constructor. e.g., Int(1).Uint() will panic. This should ensure we will never get inaccurate values.
Similarly, Parsing "Infinity" as +Inf is also removed This feature is not standard and should not be enabled by default. If this is really desired, user can still write a wrapper that invokes Float or String conditionally. Instead of embedding the maybe undesired branches in jsontext. It is harder to get consistent API design with the new RawToken refactor. Now Token.Float() should only process tokens returned by jsontext.Float, we need to differentate infinity float and infinity string. So what kind should the infinity float be? - if '0': Good for that it cannot be used as object key, but can make Token.String() confusing; also confusing for that a '0' token actually encodes to string. - if '"': Need many extra branching in Token.Kind and Token.appendString. And the kind returned by jsontext.Float() is not consistent. So, just remove these.
Hi, thanks for the contribution. I don't see a compelling reason to increase the API surface by an extra type, several methods, and break symmetry between tok, ... = dec.ReadToken()
f, err := strconv.ParseFloat(tok.String(), 64) or val, ... = dec.ReadValue()
f, err := strconv.ParseFloat(string(val), 64) The In the future, if we want to add a checked form of parsing functionality, we can add |
Decoder now returns RawToken instead of Token. RawToken exposes a new set of methods:
They reuses the same logic of arshalers, intended to offers Decoder user a more efficient and convenient way to parse numbers.
New jsontext.Raw and Token.Raw func are added to convert between RawToken and Token.
The original Float, Int, Uint methods now only support the case where the Token is created by the correspond constructor. e.g., Int(1).Uint() will panic. This should ensure we will never get inaccurate values.
Other behavior changes:
nonfinite
is still supported in json package.This is inspired by the idea in golang/go#63397 (reply in thread) . I expand the idea of @neild , and add a new RawToken type. Now
RawToken
is used in Decoding, it only haveParseFloat
intended for decodeToken
is still used in Encoding,Token.Float
now become a simple accessor to retrieve the value set byjsontext.Float
.With this design, we give up support for any inaccurate cases. Then we can answer the edge cases that @dsnet raised in the discussion naturally:
strconv.ParseInt
strconv.ParseInt