Каков общепринятый способ отправки 64-битных значений через JSON?

Некоторые из моих данных представляют собой 64-битные целые числа. Я хотел бы отправить их в программу JavaScript, работающую на странице.

Однако, насколько я могу судить, целые числа в большинстве реализаций JavaScript представляют собой 32-битные числа со знаком.

Кажется, у меня есть два варианта:

  1. Отправить значения в виде строк
  2. Отправлять значения как 64-битные числа с плавающей запятой

Вариант (1) не идеален, но вариант (2) кажется гораздо менее идеальным (потеря данных).

Как вы справились с этой ситуацией?

горе программистам, попавшим на эту страницу!

duhaime 06.04.2020 04:23
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
30
1
24 819
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Сам JSON не заботится об ограничениях реализации. ваша проблема в том, что JS не может обрабатывать ваши данные, а не протокол. Другими словами, ваш код JS-клиента должен использовать любой из этих несовершенных вариантов.

Ответ принят как подходящий

Кажется, это меньше проблема с JSON, а больше проблема с самим Javascript. Что вы собираетесь делать с этими числами? Если это просто волшебный токен, который вам нужно будет передать обратно на веб-сайт позже, во что бы то ни стало, просто используйте строку, содержащую значение. Если вам действительно нужно выполнять арифметические действия со значением, вы могли бы написать свои собственные процедуры Javascript для 64-битной арифметики.

Одним из способов представления значений в Javascript (и, следовательно, JSON) было бы разделение чисел на два 32-битных значения, например.

  [ 12345678, 12345678 ]

Чтобы разделить 64-битное значение на два 32-битных, сделайте что-то вроде этого:

  output_values[0] = (input_value >> 32) & 0xffffffff;
  output_values[1] = input_value & 0xffffffff;

Затем, чтобы рекомбинировать два 32-битных значения в 64-битное значение:

  input_value = ((int64_t) output_values[0]) << 32) | output_values[1];

Когда я пробую «input_value >> 32», я просто возвращаю «input_value», как будто 32 бита просто полностью переносятся. ">>>" имеет тот же эффект. Тем не менее, когда я пробую «Math.floor (input_value / 4294967296)» (4294967296 = Math.pow (2, 32)), я получаю старшую 32-битную часть «input_value»; Что мне не хватает?

snapfractalpop 04.07.2012 19:49

Вы не говорите, какой язык используете, поэтому я предполагаю, что вы используете Java. Является ли input_value длинным (например, 64-битным целым числом)? Если это int (32-битное целое число), то сдвиг влево на 32 бита работать не будет.

Simon Howard 05.07.2012 22:35

извините за это .. Я должен был быть откровенным. Я использую javascript (в nodejs) и был действительно удивлен, увидев, что сдвиг на 32 бита вправо каким-то образом дал мне то же число. Я не совсем понимаю все неявные преобразования типов в javascript и их базовые представления.

snapfractalpop 06.07.2012 07:46

Это по-прежнему является проблема JSON, а не проблема Javascript, поскольку JSON не поддерживает целые числа с более чем 9 десятичными цифрами. Если бы это было так, реализация Javascript была бы вынуждена обеспечивать его поддержку каким-то образом под капотом.

Lightness Races in Orbit 22.09.2012 17:18

@LightnessRacesinOrbit, похоже, я не могу найти ссылку на оператор 9 десятичных цифр. Это в какой-то спецификации?

akhaku 30.03.2013 01:28

@akhaku: Это версия спецификации (RFC 4627 и www.json.org), которую я придумал в своей голове, когда неправильно истолковал грамматику. :)

Lightness Races in Orbit 30.03.2013 18:15

Представление числа JS - это стандартное двойное значение ieee, поэтому вы не можете представить 64-битное целое число. iirc вы получаете, возможно, 48 бит фактической точности int в двойном, но все битопы JS уменьшаются до 32-битной точности (это то, что требует спецификация. yay!), поэтому, если вам действительно нужен 64-битный int в js, вам нужно будет реализовать свой собственный 64-битная логическая библиотека int.

53 бита всегда, без учета знака.

quadrupleslap 28.06.2017 10:29

Тип Javascript Number (64-битный IEEE 754) имеет только около 53 бит точности.

Но если вам не нужно выполнять какое-либо сложение или умножение, вы можете сохранить 64-битное значение в виде 4-символьных строк, поскольку JavaScript использует UTF-16.

Например, 1 можно закодировать как «\ u0000 \ u0000 \ u0000 \ u0001». Это имеет то преимущество, что сравнение значений (==,>, <) работает со строками, как и ожидалось. Также кажется простым писать битовые операции:

function and64(a,b) {
    var r = "";
    for (var i = 0; i < 4; i++)
        r += String.fromCharCode(a.charCodeAt(i) & b.charCodeAt(i));
    return r;
}

Это умный способ сэкономить на байтах, передаваемых по сети, и при этом иметь возможность более или менее считывать число. Мне было бы интересно узнать, есть ли у этого подхода какие-то подводные камни.

acjay 10.11.2017 16:30

Фактически существует ограничение на уровне точности JavaScript / ECMAScript 53-битным для целых чисел (они хранятся в мантиссе «двойного» 8-байтового буфера памяти). Таким образом, передача больших чисел в виде JSON не будет десериализована, как ожидалось клиентом JavaScript, который усечет их до своего 53-битного разрешения.

> parseInt("10765432100123456789")
10765432100123458000

См. Функцию Константа Number.MAX_SAFE_INTEGER и Number.isSafeInteger():

The MAX_SAFE_INTEGER constant has a value of 9007199254740991. The reasoning behind that number is that JavaScript uses double-precision floating-point format numbers as specified in IEEE 754 and can only safely represent numbers between -(2^53 - 1) and 2^53 - 1.

Safe in this context refers to the ability to represent integers exactly and to correctly compare them. For example, Number.MAX_SAFE_INTEGER + 1 === Number.MAX_SAFE_INTEGER + 2 will evaluate to true, which is mathematically incorrect. See Number.isSafeInteger() for more information.

Из-за разрешения чисел с плавающей запятой в JavaScript использование предложенных вами «64-битных чисел с плавающей запятой» будет иметь то же ограничение.

ИМХО лучший вариант - передавать такие значения в виде текста. Это будет по-прежнему отлично читаемый контент JSON, и с ним будет легко работать на уровне JavaScript.

Представление "чистой строки" - это то, что OData указывает для своих типов Edm.Int64 или Edm.Decimal.

В этом случае Twitter API добавляет конкретное поле ".._str": в JSON, как таковое:

{
   "id": 10765432100123456789,           // for JSON compliant clients
   "id_str": "10765432100123456789",     // for JavaScript
    ...
}

Мне очень нравится этот вариант, поскольку он по-прежнему будет совместим с клиентами с поддержкой int64. На практике такой дублированный контент в JSON не сильно повредит, если его сжать / сжать на уровне HTTP.

После передачи в виде строки вы можете использовать библиотеки, такие как strint - библиотека JavaScript для целых чисел в строковой кодировке, для обработки таких значений.

Обновлять: Более новые версии движков JavaScript включают в себя класс объектов BigInt, который может обрабатывать более 53 бит. Фактически, его можно использовать для сколь угодно больших целых чисел, поэтому он хорошо подходит для 64-битных целочисленных значений. Но при сериализации как JSON значение BigInt будет сериализован как строка JSON - как ни странно, но для совместимости, я думаю.

Отличное объяснение. Я только что столкнулся с этим с интерфейсом JS и серверной частью веб-API C#. Мой HttpResponseMessage сериализует мои объекты (которые содержат длинные идентификаторы), и они усекаются. Что было действительно странно, они не усекались, пока не попали в браузер. Если я создал ответ, а затем проанализировал контент перед его отправкой, идентификаторы не были усечены. Только когда браузер получил и проанализировал ответ, он волшебным образом усек. Ваше объяснение помогло мне понять, почему. Спасибо! В итоге я зарегистрировал собственный конвертер для длинных типов.

Kris Coleman 28.04.2017 18:04

Это случилось со мной. При отправке больших целых чисел через json в JSON.parse разразился ад. Я потратил дни на отладку. Проблема сразу же решена, когда я передал значения в виде строк.

Использовать { "the_sequence_number": "20200707105904535" } вместо { "the_sequence_number": 20200707105904535 }

Что еще хуже, может показаться, что там, где реализован каждый JSON.parse, есть некоторая общая библиотека между Firefox, Chrome и Opera, потому что все они вели себя точно так же. Сообщения об ошибках Opera содержат ссылки на URL-адреса Chrome, почти как WebKit, используемый браузерами.

console.info('event_listen[' + global_weird_counter + ']: to be sure, server responded with [' + aresponsetxt + ']');
var response = JSON.parse(aresponsetxt);
console.info('event_listen[' + global_weird_counter + ']: after json parse: ' + JSON.stringify(response));

Я получил такое поведение, когда математика с указателями пошла ужасно плохо. Призраки вылетали из моего рабочего места, сея хаос во сне. Они все изгнаны теперь, когда я перешел на струнные.

Разве это не проблема Javascript, а не JSON.

user48956 03.11.2020 21:51

Видно так. Прочтите stackoverflow.com/questions/9643626/…

Desmond Coertzen 05.11.2020 02:33

Другие вопросы по теме