Есть ли простой способ настроить форматирование массивов с помощью JSON.stringify? - PullRequest
0 голосов
/ 19 декабря 2018

Я часто хочу «красиво печатать» (включая лишние пробелы, чтобы людям было легче интерпретировать) объекты JavaScript, и для этого обычно достаточно JSON.stringify(myObject, null, " ").Однако во многих случаях есть массивы чисел, которые я действительно не хочу разбивать на новые строки.

Есть ли простой / элегантный способ сделать это с помощью функции native JSON.stringify ?

Я попытался использовать функцию «replacer»но это, кажется, только облегчает изменение (например, изменение данных), фильтрацию (например, пропуск данных) и побочные эффекты (например, данные журнала) - см. также Как использовать функцию заменителя с JSON Stringify? ,

Кроме того, существует ли уже установленный модуль / библиотека / утилита для этого или я должен написать свой собственный?

Похоже, много результатов поискана npm.org для «stringify» , но те, что я видел, кажутся просто вариациями, которые либо работают более эффективно в конкретной проблемной области, либо избегают проблем, связанных с циклическими / циклическими структурами данных.

const obj = {
  foo: "bar",
  oneLine: [1,2,3],
  multipleLines: [{
    name: "X",
    alsoOneLine: [4,5,6]
  }, {
    name: "Y"
  }]
};

document.write(`
  
    // This isn't the output I want. 
    // The arrays containing only numbers should have their elements
    // all printed on the same line.
    ${JSON.stringify(obj, null, "  ")}
  
`);

1 Ответ

0 голосов
/ 19 декабря 2018

Вы можете использовать регулярное выражение для поиска в строковой версии массивов чисел и замены пробелов во всех этих массивах чисел пустой строкой.Привязав начало шаблона к началу строки с ^, вы можете убедиться, что соответствующая пара ключ-значение (или простое значение, если массив чисел содержится в другом массиве) равна массив , а не что-то другое, например строка, содержащая нечто, похожее на JSON-массив чисел:

const obj = {
  foo: "bar",
  oneLine: [1, 2, 3],
  multipleLines: [{
    name: "X",
    alsoOneLine: [4, 5, 6],
    inner: [
      [1, 2, 3],
      [4, 5, 6]
    ]
  }, {
    name: "Y"
  }]
};

const stringified = JSON.stringify(obj, null, "  ");
const numArraysOnOneLine = stringified.replace(
  /^( *)("[^"]+": )?(\[(?:\s+\d+,)*\s+\d+\s+\])/gm,
  (_, leadingWhitespace, possibleKeyStr='', arrStr) => (
    leadingWhitespace + possibleKeyStr + arrStr.replace(/\s+/g, ''
  ))
);
document.write(`${numArraysOnOneLine}
`);

https://regex101.com/r/XfuqoT/1

Шаблон

^( *)("[^"]+": )?(\[(?:\s+\d+,)*\s+\d+\s+\])

означает:

  • ^ - сопоставить начало строки
  • ( *) Первая группа захвата: захватить начальный пробел
  • ("[^"]+": )? Вторая группа, необязательно: сопоставить двойнойключ в кавычках, если массив содержится в объекте
  • \[ - начало третьей группы.Совпадение с литералом [
  • (?:\s+\d+,)* - повторение группы пробельных символов с последующими цифрами ноль или более раз
  • \s+\d+\s+ - сопоставление последнего элемента в массиве (не имеет конечного знака)запятая): пробел, за которым следует цифра, затем еще пробел
  • \] - с последующим завершением ] (конец третьей группы)

Если цифрыможет также содержать десятичные дроби, затем замените \d+ на \d+(?:\.\d+)?, чтобы учесть необязательные десятичные цифры.

Если свойства объекта также могут содержать двойные кавычки (экранируются обратной косой чертой при строковом преобразовании), тогда замените [^"]+ с (?:[^"]|\\")+ https://regex101.com/r/XfuqoT/2

...