Преобразование строки JSON в объект с выборочной оценкой - PullRequest
3 голосов
/ 14 июля 2009

У меня есть строка:

"{0:16970861903381446063,length:1}"

Я пытался преобразовать его в объект, используя метод eval, но он также вычисляет строку и, следовательно, округляет числовое значение, возвращая:

{0:16970861903381447000,length:1}

Я пытался передать число в виде строки перед тем, как вызвать eval, использование 16970861903381446063 + '' в качестве значения при создании строки JSON; проверка его с помощью typeof показывает, что он имеет тип string, но он все еще округляет число 16970861903381446063 до 16970861903381447000.

Есть ли способ, которым я могу обойти это, или лучший способ сделать это?

Ниже приведен код, который генерирует текст json из массива, содержащего числа

function simplify(arr){
      request = "{";
      if (arr.length ==1){
         request += 0 +  ":" + (arr[0] + '')  + "," ; 
      }
      else{
         for (var i=0;i<=arr.length-1  ;i++){

        request +=  i +  ":" +  (arr[i] + '')  + ",";
     }
    }
   request += "length" + ":" + arr.length +"}";
   return request;
 }

Ответы [ 4 ]

3 голосов
/ 14 июля 2009

Вы столкнулись с точностью поплавка двойной точности IEEE, которая использует 53 бита для мантиссы и 11 бит для экспоненты.

Числа Javascript, ВСЕ из них, представлены 64-битными числами с плавающей запятой. Числа с плавающей точкой во многих языках представлены двумя частями - мантиссой и показателем степени. В Javascript мантисса составляет 53 бита, а показатель степени - 11 бит.

Когда вы видите числа, выраженные, например, как 3,5346367e + 22, мантисса равна 3,5246367, а показатель степени равен 22.

Числа, которые вы пытаетесь сохранить, больше максимального значения мантиссы, поэтому ваши числа округляются, а большие числа получают показатель степени.

Короче говоря, если вы не выполняете арифметические операции с этими огромными числами, вы должны хранить их в виде строки.

Наконец, вы должны выражать JSON Arrays как фактические JSON Arrays, а не как объекты, которые притворяются массивами, определяя целочисленные ключи и свойство length:

// Do this
json = '["16970861903381446063"]';

// Not this
json = '{0:"16970861903381446063", length:1}';
3 голосов
/ 14 июля 2009

Просто заключите его в кавычки, чтобы сделать строку:

{
    0: "16970861903381446063",
    length: 1
}

Я предполагаю, что вы просто используете это где-то в документе; или вы планируете использовать его как фактическое число?

2 голосов
/ 14 июля 2009

Звучит так, как будто вам нужно держать строку на протяжении всего пути. Однако, если вы сделаете это, как вы планируете делать какие-либо математические с этим?

0 голосов
/ 14 июля 2009

Хорошо, нашли простое решение благодаря людям на freenode

 function simplify(arr){
       request =  "{";
       if (arr.length ==1){
          request += ( 0 +  ":" + "'" + String(arr[0])+ "'" + ",") ; 
      }
       else{
          for (var i=0;i<=arr.length-1  ;i++){
             request +=  i +  ":" + "'" + String(arr[i]) + "'"  + ",";
      }

     }
      request += "length" + ":" + arr.length +"}" ;
return request;
    }

Проблема была с eval, хотя я использовал массив со строковыми литералами, они были числами, а eval требовалась строка, которая не могла быть eval () 'ed.

Ниже приведен пример вывода после явного добавления кавычек в строки

{0:'16970861903381446063',1:'16970861903381444012',length:2}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...