ugorji / go

idiomatic codec and rpc lib for msgpack, cbor, json, etc. msgpack.org[Go]
MIT License
1.83k stars 294 forks source link

Add `DecodeOptions.IntType` and `DecodeOptions.FloatType` ? #399

Closed extemporalgenome closed 8 months ago

extemporalgenome commented 1 year ago

DecodeOptions.MapType is useful for ensuring schemaless decoding compatibility of maps with encoding/json (such as by forcing map[string]any instead of map[any]any).

However, this codec library has a few areas where it's not able to be made compatible without considerable work, one of which is number handling.

stdlib JSON, by default, decodes numbers to float64; this package decodes to int64, uint64, or float64, and the uint64 bit also can be awkward for values that sometimes merely happen to be non-negative. The stdlib also provides json.Number (a string type) to preserve numbers with precision or range beyond what a uint64 or int64 can represent.

I propose that DecodeOptions receive new IntType and FloatType fields (both reflect.Type), each of which can be set to any numeric type, any type derived from string or []byte, or, specially, codec.Raw.

Setting both fields to float64 would align with default stdlib behavior. If set to string or []byte, the result should be interpretable by both strconv.ParseFloat, and should be valid JSON as well; setting both IntType and FloatType to json.Number would provide further stdlib compatibility.

Use of codec.Raw would store the encoded bytes uninterpreted (for JSON, it'd have the same behavior as setting IntType to []byte).

ugorji commented 8 months ago

JsonHandle.PreferFloat = true should be sufficient for json compatibility.

I've never been a big fan of json.Number. It was a design smell done as a hack, to accomodate encoding/json's limitations without making any significant change to the API or behaviour.

Please add comments and tag me if you think there's still some work to do.