У меня есть следующий текст:
{"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"]}}
Числа могут быть с плавающей точкой, отрицательными и нормальными.
Если вы действительно не можете изменить оригинальный 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
.
Если бы я собирался использовать что-то подобное в производстве, я бы написал накладную нагрузку модульных тестов, чтобы убедиться, что она действительно работает.
У вас просто есть цикл для проверки значения - это число или значение 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);
Если вам действительно нужно сделать это с помощью регулярного выражения, тогда вы можете попробовать это.
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);
UPDATE AS за комментарий:
(\:\s*|,|\[|\{)\s*(-?\d+(?:\.\d+)?)(?=[,\]\}])
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);
"test 123.32"
найденного в исходных тестовых данных.
Вы можете прокручивать данные и преобразовывать их в строку, как показано ниже:
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);
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 (пункт)
Сначала проанализировать их в объект 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 );