google / json_serializable.dart

Generates utilities to aid in serializing to/from JSON.
https://pub.dev/packages/json_serializable
BSD 3-Clause "New" or "Revised" License
1.55k stars 395 forks source link

Serialize a custom high-precision type as a json number (without quotes) #1325

Closed rockgecko-development closed 1 year ago

rockgecko-development commented 1 year ago

How do I serialize a custom high precision number type (eg BigDecimal ) to json without having quotation marks added to the output? ie {"precise":0.123456789012345678901234567890}

For example:

class MyPayload{
@JsonKey(
      name: 'precise',
      includeIfNull: false,
      fromJson: bigDecimalFromJson,
      toJson: bigDecimalToJson)
BigDecimal? precise;
MyPayload(this.precise);
static const fromJsonFactory = _$MyPayloadFromJson;
  static const toJsonFactory = _$MyPayloadToJson;
  Map<String, dynamic> toJson() => _$MyPayloadToJson(this);
}
BigDecimal? bigDecimalFromJson(dynamic jsonElement) =>
    jsonElement == null ? null : BigDecimal.parse(jsonElement.toString());
dynamic bigDecimalToJson(BigDecimal? value) =>
    value == null ? null : value.toString();

// test:

test('json encode BigDecimal', () {
    var task = MyPayload(
        precise: BigDecimal.parse("0.123456789012345678901234567890"));
    var jsonStr = json.encode(task.toJson()); //or json.encode(task) gives same result
    print(jsonStr);
    expect(
      jsonStr,
      '{"precise":0.123456789012345678901234567890}', //expect a json number type, meaning no quotes
    );
  });

Result:

Expected: '{"precise":0.123456789012345678901234567890}' Actual: '{"precise":"0.123456789012345678901234567890"}' Which: is different.

Thinking the serializer relies on some sort of is num check, I considered trying to put BigDecimal in a wrapper that extends num, but that's impossible:

class BigDecimalWrapper extends num{
  final BigDecimal? value;
  String toString()=> value.toString();
  String toStringAsPrecision(int precision)=>value.toString();
  //etc
  BigDecimalWrapper(this.value);
}

Result:

classes can't extend num

The recommendation from related issue #943 is to use a custom data type, which I'm doing. Now what?

Cheers

kevmoo commented 1 year ago

You MUST use quotes if you are using the embedded Dart encode/decode logic because this logic ALWAYS uses Dart's numeric type.

We don't support extending our in-box numeric type, sadly.