JavaScript регулярное выражение для сопоставления чисел в массиве

1

У меня есть следующий текст:

 {"status": "ok","data": {"grpd": 0,"obj": 073741824,"objInst": 0,"no": null,"values": [3.523422,0,-323123123,3.423,9223372036854775807,0,"test 123.32",0,0,"",0,0]}}

Мне нужно сопоставить и разместить кавычки вокруг чисел в массиве "значения", поэтому его результат должен быть:

 {"status": "ok","data": {"grpd": 0,"obj": 073741824,"objInst": 0,"no": null,"values": ["3.523422","0","-323123123","3.423","9223372036854775807","0","test 123.32","0","0","","0","0"]}}

Числа могут быть с плавающей точкой, отрицательными и нормальными.

  • 2
    Используйте анализатор JSON. Если бы я мог прокомментировать это дюжину раз, я бы так и сделал. Вы могли бы использовать регулярное выражение по пути, но регулярное выражение не должно быть основным решением здесь, я думаю.
  • 2
    Зачем делать числа в строках? Если есть одна вещь, которую я узнал, так это то, что примитивные типы сохраняют свой нативный тип.
Показать ещё 4 комментария
Теги:
match
replace

6 ответов

0
Лучший ответ

Если вы действительно не можете изменить оригинальный JSON, чтобы использовать строки для чисел, которые не входят в диапазон, поддерживаемый JS, вы можете использовать что-то вроде этого:

var json = '{"status": "ok","data": {"grpd": 0,"obj": 073741824,"objInst": 0,"no": null,"values": [3.523422,0,-323123123,3.423,9223372036854775807,0,"test 123.32",0,0,"",0,0, "test \\u0022 123", "test \\" 123"]}}';

var inString = false;
var inNumber = false;
var out = '';

for (var index = 0, len = json.length ; index < len ; ++index) {
    var chr = json.charAt(index);
    
    switch (chr) {
        case '"':
            inString = !inString;
            break;
            
        case '\\':
            out += chr + json.charAt(index + 1);
            ++index;
            continue;
            
        case '-':
        case '.':
        case '0':
        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
        case '7':
        case '8':
        case '9':
            if (!inString && !inNumber) {
                out += '"';
                inNumber = true;
            }
            
            break;
            
        default:
            if (inNumber) {
                inNumber = false;
                out += '"';
            }
    }
    
    out += chr;
}

console.log(out);

Обработка чисел в строках слишком сложна с помощью RegExp, поэтому я даже не пробовал. Я предположил, что JSON действительно... мой сырой парсер не справится вообще, если это не так. Я также проигнорировал нотацию 7e5 для чисел, для чего потребуется немного дополнительной работы, чтобы избежать соответствия e в true.

Я явно не нацеливал values массива, но он мог быть соответствующим образом адаптирован. Как именно вы это сделаете, зависит от того, хотите ли вы справиться с универсальным JSON или чем-то более ориентированным на ваш точный формат. Например, вы можете добавлять котировки только по номерам, например, до определенной длины. Это было бы легко добавить путем отслеживания точного индекса, за которым начинается число, а не только с помощью флага isNumber.

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

1

У вас просто есть цикл для проверки значения - это число или значение float и преобразование в строку.

var obj1 = {"status": "ok","data": {"grpd": 0,"obj": 073741824,"objInst": 0,"no": null,"values": [3.523422,0,-323123123,3.423,9223372036854775807,0,"test 123.32",0,0,"",0,0]}};

obj1.data.values.forEach(function(value, index, theArray) {
 if (!isNaN(value) || value.toString().indexOf('.') != -1)
    {
       theArray[index] = value.toString();
    }
});

console.log(obj1);
  • 0
    Спасибо за ответ, но большие цифры будут потеряны с этим методом.
  • 0
    Javascript не поддерживает большие числа, так как они усекают их, поэтому для их сохранения необходимо отправить их в виде строки с самого сервера
Показать ещё 1 комментарий
1

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

const regex = /(-?\d+(\.\d+)?)(?![^,]*")/g;
const str = '{"status": "ok","data": {"grpd": 0,"obj": 073741824,"objInst": 0,"no": null,"values": [3.523422,0,-323123123,3.423,9223372036854775807,0,"test 123.32",0,0,"",0,0]}}';
const subst = '"$1"';

const result = str.replace(regex, subst);

console.log(result);

Демо-версия Regex

UPDATE AS за комментарий:

(\:\s*|,|\[|\{)\s*(-?\d+(?:\.\d+)?)(?=[,\]\}])

Демонстрация 2

const regex = /(\:\s*|,|\[|\{)\s*(-?\d+(?:\.\d+)?)(?=[,\]\}])/g;
const str = '{"status": "ok","data": {"grpd": 0,"obj": 073741824,"objInst": 0,"no": null,"values": [3.523422,0,-323123123,3.423,"test 123.3,2",0,"test 123.32",0,0,"","adsa22s22",0]}}';
const subst = '$1"$2"';


const result = str.replace(regex, subst);

console.log(result);
  • 0
    Большое спасибо, это работает!
  • 0
    Я не верю, что это работает для примера "test 123.32" найденного в исходных тестовых данных.
Показать ещё 11 комментариев
1

Вы можете прокручивать данные и преобразовывать их в строку, как показано ниже:

var data =  {"status": "ok","data": {"grpd": 0,"obj": 073741824,"objInst": 0,"no": null,"values": [3.523422,0,-323123123,3.423,9223372036854775807,0,"test 123.32",0,0,"",0,0]}}

var values = [];

for (var i = 0 ; i < data.data.values.length ; i ++) {
    values.push(String(data.data.values[i]));
}

data.data.values = values;

console.log(data);
0
let obj = JSON.parse(response);
obj.values = obj.values.map(item => typeof item === 'number' ? '"'+item+'"');
console.log(JSON.stringify(obj));

или с es5

obj.values = obj.values.map(function(item) {
  return typeof item === 'number' ? '"'+item+'"';
}

или вместо typeof item === 'number' вы можете использовать! IsNaN (пункт)

  • 0
    Когда я нажимаю на первую строку "let obj = JSON.parse (response);" Я потерял большие цифры, потому что JS их не поддерживает. В любом случае, спасибо, некоторые парни выше дают мне хорошее регулярное выражение.
0

Сначала проанализировать их в объект JS

var obj = JSON.parse( jsonString );

затем

obj.data.values = obj.data.values.map( function( item ){ return !isNaN( item ) ? String( item ) : item; });

Преобразуйте его в формат строки JSON

jsonString  = JSON.stringify( obj );

Однако, если цифры находятся за пределами объектов javascript, то используйте это решение на основе регулярных выражений

var str = '{"status": "ok","data": {"grpd": 0,"obj": 073741824,"objInst": 0,"no": null,"values": [3.523422,0,-323123123,3.423,9223372036854775807,0,"test 123.32",0,0,"",0,0]}}';

str = str.replace(/[,|\[](\-){0,1}\d+(\.\d+)*(?=[,|\]])/g, function(match){ var firstChar = match.charAt(0); match = match.substring( 1 ); return firstChar + "\"" + match + "\"" ; });

console.log( str );
  • 0
    Я конвертирую их, потому что мне нужно работать с большими числами, которые не поддерживает JS, мне нужно только получить эти значения и разместить их на странице. Большое число это: 9223372036854775807. Попробуйте разместить его на вашей консоли, как число. Если есть лучший способ сделать это, я буду счастлив использовать его, но я не знаю этого. Поэтому я конвертирую их в строку, а затем анализирую их с помощью анализатора JSON.
  • 0
    @MilenGrigorov Я понял это сейчас, парсинг к подходу json / number не сработает.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню