Кажется, это не столько проблема с JSON, сколько проблема с самим Javascript. Что вы планируете делать с этими цифрами? Если это просто волшебный токен, который вам нужно передать обратно на веб-сайт позже, во что бы то ни стало, просто используйте строку, содержащую значение. Если вам действительно нужно выполнять арифметические действия со значением, вы могли бы написать свои собственные подпрограммы Javascript для 64-битной арифметики.
Одним из способов представления значений в Javascript (и, следовательно, JSON) было бы разделение чисел на два 32-битных значения, например.
[ 12345678, 12345678 ]
Чтобы разделить 64-битное значение на два 32-битных значения, сделайте что-то вроде этого:
На самом деле существует ограничение на уровне точности JavaScript/ECMAScript до 53 бит для целых чисел (они хранятся в мантиссе двойного буфера памяти размером 8 байт). Таким образом, передача больших чисел в формате JSON не будет десериализована, как ожидается клиентом JavaScript, который усекает их до 53-битного разрешения.
Константа MAX_SAFE_INTEGER имеет значение 9007199254740991. Причина этого числа заключается в том, что JavaScript использует числа формата с плавающей запятой двойной точности, как указано в IEEE 754, и может безопасно представлять только числа между -(2^53 - 1) и 2^53 - 1.
Безопасный в этом контексте относится к способности точно представлять целые числа и правильно их сравнивать. Например, Number.MAX_SAFE_INTEGER + 1 === Number.MAX_SAFE_INTEGER + 2 будет равно true, что математически неверно. См. Number.isSafeInteger() для получения дополнительной информации.
Из-за разрешения поплавков в JavaScript использование 64-битных чисел с плавающей запятой, как вы предложили, будет страдать от того же ограничения.
ИМХО лучший вариант - передавать такие значения как текст. Это будет по-прежнему прекрасно читаемый контент JSON, и с ним будет легко работать на уровне JavaScript.
Что делает Twitter API в этом случае, так это добавляет конкретное поле ".._str": в JSON, как таковое:
{
"id": 10765432100123456789, // for JSON compliant clients
"id_str": "10765432100123456789", // for JavaScript
...
}
Мне очень нравится этот вариант, так как он по-прежнему совместим с клиентами с поддержкой int64. На практике такой дублированный контент в JSON не сильно повредит, если его сдуть/заархивировать на уровне HTTP.
Обновление. Новые версии движков JavaScript включают BigInt объектный класс, способный обрабатывать более 53-бит. На самом деле его можно использовать для произвольно больших целых чисел, поэтому он хорошо подходит для 64-битных целых чисел. Но при сериализации в формате JSON значение BigInt будет сериализоваться как строка JSON - как ни странно, но я думаю, в целях совместимости.
Ответ 3 · рейтинг 6 · David Leonard
Тип Javascript Number (64-битный IEEE 754) имеет только около 53 бит точности.
Но если вам не нужно выполнять сложение или умножение, вы можете сохранить 64-битное значение в виде 4-символьной строки, поскольку JavaScript использует UTF-16.
Например, 1 может быть закодировано как " ". Это имеет то преимущество, что сравнение значений (==, >, ‹) работает со строками, как и ожидалось. Также кажется простым писать битовые операции:
function and64(a,b) {
var r = "";
for (var i = 0; i < 4; i++)
r += String.fromCharCode(a.charCodeAt(i) & b.charCodeAt(i));
return r;
}
Ответ 4 · рейтинг 2 · olliej
Представление числа JS является стандартным ieee double, поэтому вы не можете представить 64-битное целое число. iirc вы получаете, возможно, 48 бит фактической точности int в двойном, но все биты JS уменьшаются до 32-битной точности (это то, что требует спецификация, ура!), поэтому, если вам действительно нужен 64-битный int в js, вам нужно будет реализовать свой собственный 64-битная библиотека встроенной логики.
Ответ 5 · Javier
Сам JSON не заботится об ограничениях реализации. ваша проблема в том, что JS не может обрабатывать ваши данные, а не протокол. Другими словами, ваш клиентский код JS должен использовать любой из этих несовершенных вариантов.
Ответ 6 · Desmond Coertzen
Это случилось со мной. Весь ад разразился при отправке больших целых чисел через json в JSON.parse. Я провел дни, пытаясь отладить. Проблема сразу же решилась, когда я передал значения в виде строк.
Используйте { "the_sequence_number": "20200707105904535" } вместо { "the_sequence_number": 20200707105904535 }
Что еще хуже, может показаться, что там, где реализован каждый JSON.parse, есть какая-то общая библиотека между Firefox, Chrome и Opera, потому что все они вели себя одинаково. Сообщения об ошибках Opera содержат ссылки на URL-адреса Chrome, почти как WebKit, используемый браузерами.
console.log('event_listen[' + global_weird_counter + ']: to be sure, server responded with [' + aresponsetxt + ']');
var response = JSON.parse(aresponsetxt);
console.log('event_listen[' + global_weird_counter + ']: after json parse: ' + JSON.stringify(response));
Поведение, которое я получил, было таким, когда математика указателя пошла ужасно плохо. Призраки вылетали из моей рабочей станции, сея хаос во сне. Теперь, когда я перешел на струны, они все изгнаны.