Подтвердить что ты не робот

Как разбирать строку JSON, содержащую "NaN" в Node.js

У вас есть приложение node.js, которое получает строки данных JSON, которые содержат литерал NaN, например

 "[1, 2, 3, NaN, 5, 6]"

Сбой JSON.parse(...) в node.js. Я хотел бы проанализировать его, если я могу в объект.

Я знаю, что NaN не входит в спецификацию JSON. Большинство ссылок SO (отправка NaN в json) позволяют исправить выход.

Здесь, хотя данные создаются на сервере, который я не контролирую, это коммерческая библиотека Java, где я могу видеть исходный код. И это было сделано в библиотеке Google Gson:

private Gson gson = (new GsonBuilder().serializeSpecialFloatingPointValues().create()); 
... 
gson.toJson(data[i], Vector.class, jsonOut)

Итак, это похоже на законный источник. И согласно Gson API Javadoc, он говорит, что я должен разбираться в нем:

Раздел 2.4 спецификации JSON запрещает специальные двойные значения (NaN, Infinity, -Infinity). Однако спецификация Javascript (см. раздел 4.3.20, 4.3.22, 4.3.23) позволяет использовать эти значения как действительные Значения Javascript. Более того, большинство движков JavaScript будут принимать эти специальные значения в JSON без проблем. Итак, на практическом уровне это имеет смысл принимать эти значения как действительные JSON, хотя JSON спецификация запрещает их.

Несмотря на это, это не работает как в node.js, так и в Chrome: JSON.parse('[1,2,3,NaN,"5"]')

Есть ли флаг для установки в JSON.parse()? Или альтернативный синтаксический анализатор, который принимает NaN как литерал?

Я некоторое время искал Google, но, похоже, не нашел документа по этой проблеме.

PHP: как кодировать бесконечные числа или числа NaN для JSON?

4b9b3361

Ответ 1

У вас есть приложение node.js, которое получает строки данных JSON, которые содержат литерал NaN, например

Тогда ваше приложение NodeJS не получает JSON, получая текст, который смутно напоминает JSON. NaN не является допустимым токеном JSON.

Три варианта:

1. Получить источник для корректного создания JSON

Это, очевидно, предпочтительный курс. Данные не JSON, которые должны быть исправлены, что могло бы решить вашу проблему.

2. Поверните NaN простым способом:

Вы можете заменить его на null перед его разбором, например:

var result = JSON.parse(yourString.replace(/\bNaN\b/g, "null"));

... и затем обработать null в результате. Но это очень простодушное, это не позволяет возможности того, что символы NaN могут появляться в какой-то строке.

В качестве альтернативы, вращающейся идеи Matt Ball reviver (теперь удаленной), вы можете изменить ее на специальную строку (например, "***NaN***"), а затем использовать редактор, чтобы заменить его с помощью реального NaN:

var result = JSON.parse(yourString.replace(/\bNaN\b/g, '"***NaN***"'), function(key, value) {
    return value === "***NaN***" ? NaN : value;
});

... но это имеет ту же проблему, что и быть немного простеньким, предполагая, что символы NaN никогда не появятся в соответствующем месте.

3. Используйте (содрогните!) eval

Если вы знаете и доверяете источнику этих данных, и там нет возможности его подделать в пути, вы можете использовать eval для его анализа вместо JSON.parse. Поскольку eval допускает полный синтаксис JavaScript, включая NaN, это работает. Надеюсь, я сделал предостережение достаточно смелым, чтобы люди поняли, что я бы рекомендовал это только в очень, очень и очень крошечном проценте ситуаций. Но опять же, помните, что eval допускает произвольное выполнение кода, поэтому, если есть какая-либо возможность того, что строка была подделана, не используйте ее.

Ответ 2

Когда вы имеете дело с чем-либо математическим или с отраслевыми данными, NaN ужасно удобен (а часто и бесконечности). И это промышленный стандарт с IEEE754.

Очевидно, что некоторые библиотеки, в частности GSON, позволяют включать их в JSON, которые они производят, теряя стандартную чистоту и приобретая здравый смысл.

Регенерация и регулярные выражения не могут быть надежно использованы в реальном проекте при обмене сложными динамическими объектами.

И eval также имеет проблемы, один из которых является тем фактом, что он подвержен сбою в IE, когда строка JSON велика, а другая угроза безопасности.

Вот почему я написал определенный парсер (используемый в производстве): JSON.parseMore

Ответ 3

Правильное решение состоит в том, чтобы перекомпилировать синтаксический анализатор и внести в базу исходных данных логический флаг "allowNan". Это решение других библиотек (питон приходит на ум).

Хорошие библиотеки JSON будут разрешать все, что смутно напоминает JSON с установленными правильными флагами (perl JSON.pm заметно гибкий)... но при написании сообщения они создают стандартный JSON.

IE: оставьте комнату чище, чем вы ее нашли.