-
Notifications
You must be signed in to change notification settings - Fork 64
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
Add support for BigInt #156
Comments
This will be possible in the next major version using @jsonObject
class BigIntTest {
@jsonMember
big: bigint;
}
const typedJson = new TypedJSON(BigIntTest);
TypedJSON.mapType(BigInt, {
deserializer: json => BigInt(json),
serializer: value => value.toString(),
});
TypedJSON.parse({
big: '123456789123456789123456789',
}, BigIntTest); Note that here the BigInit value is represented by a string in JSON. |
Hi Matthias, thanks for the reply. While using Since BigInt is a built-in type in Typescript I would expect it to be supported as a first-class type in TypedJSON. |
I see where you're coming from but do not believe we would support this anytime soon due to the need for using a custom
Another thing to note is that while Presenting precise numbers in JavaScript has long been an issue and will probably remain one for a while longer. Perhaps https://github.com/tc39/proposal-json-parse-with-source will solve these problems. In the meantime I strongly recommend to represent numbers outside of IEEE 754 precision as strings in JSON. If strings are used then the example shown above will preserve precision. I've used the decimals represented by strings approach myself in applications that deal with money and can confirm it works perfectly. PayPal uses it too. |
Personally, I think TypedJSON.mapType(BigInt, {
deserializer: (value) => value == null ? value : BigInt(json),
serializer: (value) => value == null ? value : value.toString(),
});
@jsonObject
class MyData {
@jsonMember
public amount: BigInt = BigInt(0);
} But assigning const serializer = new TypedJSON(MyData);
const data = serializer.parse('{ "amount": "2" }');
if (!data) {
throw new Error('Failed to parse data');
}
const x: bigint = BigInt(2);
console.log(data.amount + x); // The issue is here, x is a primitive 'bigint', and data.amount is 'BigInt' So, to overcome this issue, I usually use something like this in my code: function jsonBigIntMember(): PropertyDecorator {
return jsonMember({
deserializer: (json) => (json == null ? json : BigInt(json)),
serializer: (value) => (value == null ? value : value.toString()),
});
}
@jsonObject
class MyData {
@jsonBigIntMember()
public amount: bigint = BigInt(0); // Notice it's of type 'bigint' now
}
const serializer = new TypedJSON(MyData);
const data = serializer.parse('{ "amount": "2" }');
if (!data) {
throw new Error('Failed to parse data');
}
const x: bigint = BigInt(2);
console.log(data.amount + x); // No compilation errors! |
@MatthiasKunnen maybe it'll be a good idea to add this decorator to the export const jsonBigIntMember = jsonMember({
deserializer: (json) => (json == null ? json : BigInt(json)),
serializer: (value) => (value == null ? value : value.toString()),
}); |
@rjkz808, there was a mistake in my example. There should not have been a import {jsonObject, jsonMember, TypedJSON} from 'typedjson';
TypedJSON.mapType(BigInt, {
deserializer: json => json == null ? json : BigInt(json),
serializer: value => value == null ? value : value.toString(),
});
@jsonObject
class MappedTypes {
@jsonMember
cryptoKey: bigint;
}
const result = TypedJSON.parse({cryptoKey: '1234567890123456789'}, MappedTypes);
const x = BigInt(1);
console.log(result.cryptoKey + x); |
Hi there, thanks for this awesome library. TypedJSON.mapType(BigInt, {
deserializer: json => (json == null ? json : BigInt(json)),
serializer: value => (value == null ? value : value.toString()),
});
@jsonObject
class MappedTypes {
@jsonMember
cryptoKey!: bigint;
}
const json = { cryptoKey: "1234567890123456789" };
const result = TypedJSON.parse(json, MappedTypes) as MappedTypes;
// De-serialization works
expect(result.cryptoKey + BigInt(1)).toBe(1234567890123456790n); // OK
// Serialization throws
TypedJSON.toPlainJson(result, MappedTypes);
// TypeError: Could not serialize 'MappedTypes.cryptoKey': expected 'BigInt', got 'BigInt' The problem is that the Adding a simple extra condition to ...
else if(value.constructor === constructor) {
return true;
} |
BigInt is one of the standard built-in types in Typescript. At the moment TypedJSON does not support parsing BigInt out of the box. The underlying problem is also that the standard
JSON.parse()
does not support parsing bigint - it coerces bigints intonumber
, which loses precision.Currently
BigInt
can be parsed by TypedJSON via custom de-/serializes and use of an external JSON parser that supports bigint parsing: https://github.com/sidorares/json-bigint.Suggestion: add support for BigInts to TypedJSON
The text was updated successfully, but these errors were encountered: