Node.js - Как написать / сериализовать произвольный объект JavaScript, содержащий функции и специальные значения, и сохранить его в файл .js

У меня есть объект JavaScript, который содержит функции и специальные значения, такие как Infinity, а также строки и числа:

const myObject = {
   propertyA: "my string",
   propertyB: 5,
   propertyC: () => "function returing a string",
   propertyD: Infinity
};

Я хочу сохранить его в файл, чтобы полученный контент выглядел так:

export default function () {
    return {
        propertyA: "my string",
        propertyB: 5,
        propertyC: () => "function returing a string",
        propertyD: Infinity
    };
}

Я пробовал использовать JSON.stringify(), но это не работает с функциями и специальными значениями, так как они недействительны JSON:

writeFileSync('my-output.js', `
   export default function () {
       return ${ JSON.stringify(myObject) };
   }
`);

const myObject = {
   propertyA: "my string",
   propertyB: 5,
   propertyC: () => "function returing a string",
   propertyD: Infinity
};

console.info(JSON.stringify(myObject, null, 4));

Есть ли другой способ сделать это?

в каком случае json.stringify не работает?

ashish singh 08.09.2018 19:58

JSON содержит только свойства значений, но не функции.

TLP 08.09.2018 20:02

Действительно, функции недействительны JSON, но это все еще действительный объект javascript, и я хочу написать файл javascript;)

JoG 08.09.2018 20:22
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
3
599
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вам нужен другой способ сериализации вашего объекта, кроме JSON.stringify, может быть что-то вроде этого:

// Pretty:

const TAB = '    ';
const BR = '\n';
const CBR = `,${ BR }`;

// Minified: 

// const TAB = '';
// const BR = '';
// const CBR = ',';

function arrayAsString(arr, depth=0) {
  const _ = TAB.repeat(depth - 1);
  const __ = _ + TAB;
  
  return `[${
    BR }${ arr.map(value =>
    `${ __ }${ serialize(value, depth) }`).join(CBR) }${
    BR }${ _ }]`;
}

function objectAsString(obj, depth=0) {
  const _ = TAB.repeat(depth - 1);
  const __ = _ + TAB;
  
  return `{${
    BR }${ Object.entries(obj).map(([key, value]) =>
    `${ __ }${ key }: ${ serialize(value, depth) }`).join(CBR) }${
    BR }${ _ }}`;
}

function serialize(value, depth=0) {
  if (value === null) {
    return `${ value }`;
  } else if (Array.isArray(value)) {
    return arrayAsString(value, depth + 1);
  } else if (typeof value === 'object') {
    return objectAsString(value, depth + 1);
  } else if (typeof value === 'string') {
    return `"${ value }"`;
  } else {
    return `${ value }`;
  }
}

const notStringifyableObject = {
  1: Infinity,
  str: "my string",
  num: 5,
  func: () => console.info('It works! ?'),
  mixArr: [{
    value: 1
  }, {
    value: 2
  }, 1, 2, [3, 4, 5]],
  arr: [1, 2, 3],
  obj: { foo: 'bar' },
  nil: null,
  und: undefined
};

const serialized = serialize(notStringifyableObject);

// This is what you would save in a file:
console.info(`export default ${ serialized };`);

// Check if it's actually working: 

eval(`test = ${ serialized }`);

test.func();
.as-console-wrapper {
  max-height: 100vh !important;
}

Затем, как только вы сериализовали свой объект, вы можете сохранить его представление string в файл с некоторым дополнительным кодом, чтобы вы могли позже загрузить его с помощью require, как вы уже сделали:

writeFileSync('my-output.js', `export default () => ${ serialized };`);

Или:

writeFileSync('my-output.js', `export default ${ serialized };`);

Обратите внимание, что это всего лишь базовая реализация, и она не поддерживает регулярные выражения, даты, круговые структуры ... Таким образом, вы можете предпочесть использовать такую ​​библиотеку, как serialize-javascript или serialize-to-js, вместо реализации вашего собственного решения.

он вылетает, когда значение равно нулю

JoG 08.09.2018 21:55

@JoG Исправлено. Это потому, что typeof null - это "object", поэтому должно быть условие, которое проверяет и обрабатывает это внутри serialize().

Danziger 08.09.2018 22:16

Другие вопросы по теме