Есть ли способ кодировать целочисленные значения, превышающие 32 бита, с помощью bs-json?

Я использовал строки для представления декодированных целых чисел JSON размером более 32 бит. Кажется, string_of_intспособен работать с большими целочисленными входами. Итак, декодер, записанный (в пространстве имен Json.Decode):

      id: json |> field("id", int) |> string_of_int,  /* 'id' is string */

успешно работает с целыми числами не менее 37 бит.

С другой стороны, кодирование доставляет мне хлопоты. Удаленный сервер не принимает строковое представление и ожидает int64. Можно ли сделать bs-json поддержать int64тип? Я надеялся, что что-то вроде этого заработает:

      type myData = { id: int64 };

let encodeMyData = (data:myData) => Json.Encode.(object_([("id", int64(myData.id)]))

Необходимость использовать собственный кодировщик не так страшна, как декодер, но ... я бы предпочел не делать этого.

1 ответ

Решение

Вы не говорите точно, какая у вас проблема с кодировкой. Кодировщик буквально ничего не делает, кроме изменения типа, веря, что значение действительно действительное. Поэтому я предполагаю, что именно операция вызывает проблемы. Но возникает вопрос: если вы можете успешно декодировать его как, то почему вы затем конвертируете его в string?

Основная проблема здесь в том, что в JavaScript нет 64-битных целых чисел. Максимально безопасное число - 53 - 1. JavaScript фактически не имеет целые чисел, то лишь с, который может представлять собой определенный диапазон целых чисел, но не может эффективно выполнять целочисленную арифметику , если они не преобразуются либо 32-бит или 64-битные файлы. И поэтому по какой-то причине, вероятно, согласованной обработки переполнения, в спецификации EcmaScript было решено, что двоичные побитовые операции должны работать с 32-битными целыми числами. Таким образом, это открыло возможность для внутреннего 32-битного представления, нотации для создания 32-битных целых чисел и возможность оптимизированной целочисленной арифметики над ними.

Итак, на ваш вопрос:

Было бы "безопасно" просто добавить внешний int64: int64 -> Js.Json.t = "%identity" в файлы кодировщика?

Нет, потому что в JavaScript нет 64-битного целочисленного представления, int64 значения представлены в виде массива из двух Numbers Я полагаю, но это также внутренняя деталь реализации, которая может быть изменена. Просто бросаю это на Js.Json.t не даст ожидаемого результата.

Так что можете вы тогда ?

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

В качестве альтернативы вы можете использовать <tcode id="4401361"></tcode>, который должен вести себя как floats за исключением деления, когда результат усекается до 32-битного целого числа.

Наконец, вы также можете реализовать свой собственный int_of_string создать int это технически выходит за пределы допустимого диапазона, если напрямую использовать пару облегченных функций JavaScript, хотя я бы не рекомендовал это делать:

      let bad_int_of_string = str => 
  str |> Js.Float.fromString |> Js.Math.floor_int;
Другие вопросы по тегам