Пользовательская сериализация в машинописи происходит не так, как ожидалось (массивы конвертируются в объекты с распространением) - PullRequest
1 голос
/ 25 марта 2020

1. Проблема

Я выполняю пользовательскую сериализацию в TypeScript, как показано в примере ниже.

Я сериализую все строки как пользовательские типы. При следующем подходе все строки корректно заменяются, но те , которые находятся в массивах, возвращаются как объекты . Ожидается, что массивы должны оставаться как массивы в возвращенном новом объекте, и это должно нормально работать для строк, которые существуют как в объектах, так и в массивах.

В качестве дополнительной информации я сериализую пользовательский тип, отличный от строк в моем Проект, это пример того, что я пытаюсь сделать.

Любые входы?

2. Код

interface Test {
  a: number;
  b: Array<string>
}

interface Sample {
  x: number;
  y: string;
  z: Array<Test>;
}

let sample: Sample = {
  x: 1,
  y: 'hello',
  z: [{ a: 10, b: ['hello', 'hi'] }]
};

function isObject(obj: any): boolean {
  return obj !== null && typeof obj === 'object';
}

function isString(obj: any): boolean {
  return obj !== null && typeof obj === 'string';
}

console.log(`${JSON.stringify(sample)}`);

function customSerializeRecursive(obj: any): any {
  const customTypePlaceHolder = {};

  for (const entry of Object.entries(obj)) {
    const [key, value] = entry;
    if (isString(value)) {
      customTypePlaceHolder[key] = {
        _type: 'test',
        _value: value.toString()
      };

    } else if (isObject(value)) {
      customTypePlaceHolder[key] = customSerializeRecursive(value);

    }
  }

  const newObj = { ...obj, ...customTypePlaceHolder };

  if (Object.keys(customTypePlaceHolder).length === 0) {
    return obj;
  } else {
    return newObj;
  }
}

const newSample = customSerializeRecursive(sample);
console.log(`${JSON.stringify(newSample)}`);

3. Выходные данные

{
    "x": 1,
    "y": "hello",
    "z": [{"a": 10, "b": ["hello", "hi"]}]
}

{
    "x": 1,
    "y": {"_type": "test", "_value": "hello"},
    "z":{"0": {"a": 10, "b": {"0": {"_type": "test", "_value": "hello"}, "1": {"_type": "test", "_value": "hi"}}}}
}
  • Первый json показывает переданный объект.
  • Второй json показывает возвращенный объект: мы видим, как z преобразуется в объект.

Ожидаемый результат

{
    "x": 1,
    "y": "hello",
    "z": [{"a": 10, "b": ["hello", "hi"]}]
}

{
    "x": 1,
    "y": {"_type": "test", "_value": "hello"},
    "z": [{"a": 10, "b": [{"_type": "test", "_value": "hello"}, {"_type": "test", "_value": "hi"}]}]
}

1 Ответ

0 голосов
/ 25 марта 2020

Прямой ответ на ваш квест будет таким:

const sample: Record<string, any> = {
    x: 1,
    y: 'hello',
    z: [{ a: 10, b: ['hello', 'hi'] }]
};

function replacer(key, value) {
    if (['_type', '_value'].includes(key)) {
        return value;
    }

    if (typeof value === 'string') {
        return {
            _type: 'test',
            _value: value,
        };
    }

    return value;
}

console.log(JSON.stringify(sample, replacer, 2));

, который даст вам следующий результат:

{
  "x": 1,
  "y": {
    "_type": "test",
    "_value": "hello"
  },
  "z": [
    {
      "a": 10,
      "b": [
        {
          "_type": "test",
          "_value": "hello"
        },
        {
          "_type": "test",
          "_value": "hi"
        }
      ]
    }
  ]
}

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

PS Если вы используете машинопись попробуй не использовать any.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...