Есть ли простой способ преобразовать этот JSON туда-сюда? - PullRequest
0 голосов
/ 27 февраля 2019

Мы используем Postman для тестирования API.Некоторые объекты, к которым мы возвращаемся, очень многословны и не просты в обращении, поэтому я хочу создать вспомогательный метод, чтобы сделать их немного более краткими.Я знаю, что есть все виды библиотек преобразований, таких как node-json-transform , selecttransform , jsontransforms и т. Д., Но, к сожалению, я могу использовать только Почтальон Песочница библиотеки и ванильный JS.

Я ищу самый простой (наименьшее количество loc и функций) способ преобразования этого объекта:

var verbose = [
    {
        "Key": "Name",
        "Value": "John Doe",
        "Instance": 1
    },
    {
        "Key": "Age",
        "Value": "33",
        "Instance": 1
    },
    {
        "Key": "Child",
        "Value": "Jane",
        "Instance": 1
    },
    {
        "Key": "Child",
        "Value": "Rocky",
        "Instance": 2
    }];

в этот:

var concise =  {
    "Name": "John Doe",
    "Age": "33",
    "Child": ["Jane", "Rocky"]
};

и снова вернемся в многословную форму.

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

Ответы [ 6 ]

0 голосов
/ 27 февраля 2019

Я также попробовал использовать reduce:

РЕДАКТИРОВАТЬ: без синтаксиса ..., с Object.assign и array.concat

РЕДАКТИРОВАТЬ2: Я хотел попробовать иповерните его снова.В этом коде мы теряем значение Instance: (

var verbose = [
  {
    Key: 'Name',
    Value: 'John Doe',
    Instance: 1,
  },
  {
    Key: 'Age',
    Value: '33',
    Instance: 1,
  },
  {
    Key: 'Child',
    Value: 'Jane',
    Instance: 1,
  },
  {
    Key: 'Child',
    Value: 'Rocky',
    Instance: 2,
  },
]

const concise = verbose.reduce(
  (p, n) =>
    Object.assign(p, {
      [n.Key]: !p.hasOwnProperty(n.Key)
        ? n.Value
        : typeof p[n.Key] === 'string'
        ? [p[n.Key], n.Value]
        : p[n.Key].concat(n.Value),
    }),
  {},
)

console.log(concise)
// { Name: 'John Doe', Age: '33', Child: [ 'Jane', 'Rocky' ] }

const backAgain = Object.entries(concise).reduce(
  (p, [k, v]) =>
    Array.isArray(v)
      ? p.concat(v.map(x => ({ Key: k, Value: x })))
      : p.concat({ Key: k, Value: v }),
  [],
)

console.log(backAgain)
// [ { Key: 'Name', Value: 'John Doe' },
//  { Key: 'Age', Value: '33' },
//  { Key: 'Child', Value: 'Jane' },
//  { Key: 'Child', Value: 'Rocky' } ]
0 голосов
/ 27 февраля 2019

Здесь я предполагаю, что все атрибуты являются многозначными, затем я уменьшу те, которые имеют длину 1, до простого значения.Это немного медленнее, чем при обратном подходе, когда вы предполагаете, что значения являются однозначными, и переводите их в массивы, когда они доказывают обратное, чтобы соблюдать порядок, установленный Instance.

function makeConcise(verbose) {
  let concise = {};
  verbose.forEach(({Key, Value, Instance}) => {
    if (!concise[Key]) concise[Key] = [];
    concise[Key][Instance - 1] = Value;
  });
  Object.keys(concise).forEach(Key => {
    if (concise[Key].length == 1) concise[Key] = concise[Key][0];
  });
  return concise;
}

Функция реверса также проста:

function makeVerbose(concise) {
  let verbose = [];
  Object.keys(concise).forEach(Key => {
    if (Array.isArray(concise[Key])) {
      concise[Key].forEach((Value, index) => {
        verbose.push({Key, Value, Instance: index + 1});
      });
    } else {
      verbose.push({Key, Value: concise[Key], Instance: 1});
    }
  });
  return verbose;
}
0 голосов
/ 27 февраля 2019

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

let verbose = [{
    "Key": "Name",
    "Value": "John Doe",
    "Instance": 1
  },
  {
    "Key": "Age",
    "Value": "33",
    "Instance": 1
  },
  {
    "Key": "Child",
    "Value": "Jane",
    "Instance": 1
  },
  {
    "Key": "Child",
    "Value": "Rocky",
    "Instance": 2
  }
]

let concise = {
  "Name": "John Doe",
  "Age": "33",
  "Child": ["Jane", "Rocky"]
}

verboseToConcise = (verbose) => {
  let obj = {}
  verbose.forEach(v => {
    let key = obj[v.Key]
    if (key) typeof key === 'string' ? obj[v.Key] = [key, v.Value] : key.push(v.Value)
    else obj[v.Key] = v.Value
  })
  return obj
}

conciseToVerbose = (concise) => {
  let arr = []
  Object.entries(concise).forEach(([key, value]) => {
    if (typeof value === 'object') {
      for (let i = 0; i < value.length; i++){
        arr.push({
          "Key": key,
          "Value": value[i],
          "Instance": i+1
        })
      }
    } else {
      arr.push({
        "Key": key,
        "Value": value,
        "Instance": 1
      })
    }
  })
  return arr
}

console.log(verboseToConcise(verbose))
console.log(conciseToVerbose(concise))
0 голосов
/ 27 февраля 2019
const verbose = [{
    "Key": "Name",
    "Value": "John Doe",
    "Instance": 1
  },
  {
    "Key": "Age",
    "Value": "33",
    "Instance": 1
  },
  {
    "Key": "Child",
    "Value": "Jane",
    "Instance": 1
  },
  {
    "Key": "Child",
    "Value": "Rocky",
    "Instance": 2
  }
];
let concise = {};

verbose.forEach(item => {
  const values = Object.values(item)
  if (concise[values[0]])  concise = {...concise, [values[0]]: [concise[values[0]], values[1]]};
  else concise = {...concise, ...{[values[0]]: values[1]}}
})

0 голосов
/ 27 февраля 2019

Исходя из того, как я понял ваш вопрос, вы хотите создать пары ключ-значение из массива объектов verbose.Однако, если есть конфликты клавиш, значения должны быть преобразованы в массив.

Имея это в виду, вам придется:

  1. Использовать forEach для циклического прохожденияваш массив объектов.
  2. Если ключ не конфликтует, мы просто создаем новую пару ключ-значение
  3. Если ключ конфликтует, то это становится немного сложнее:
    • Еслистолкновения клавиш, и это первое вхождение, мы преобразуем значение в паре ключ-значение в массив
    • Если столкновение ключей и это не первое вхождение, мы знаем, что смотрим на массив
    • Теперь у нас определенно есть массив, поэтому мы вставляем в него наше значение

См. Подтверждение концепции ниже:

var verbose = [{
    "Key": "Name",
    "Value": "John Doe",
    "Instance": 1
  },
  {
    "Key": "Age",
    "Value": "33",
    "Instance": 1
  },
  {
    "Key": "Child",
    "Value": "Jane",
    "Instance": 1
  },
  {
    "Key": "Child",
    "Value": "Rocky",
    "Instance": 2
  }];

var concise = {};
verbose.forEach(function(i) {
  var key = i['Key'];
  var value = i['Value'];
  
  // If item exists, we want to convert the value into an array of values
  if (key in concise) {
    var item = concise[key];
    
    // If it is not an array already, we convert it to an array
    if (!Array.isArray(item))
      item = [item];
      
    item.push(value);
    concise[key] = item;
  }
  
  // If item does not exist, we simply create a new key-value pair
  else {
    concise[key] = value;
  }
});
console.log(concise);
0 голосов
/ 27 февраля 2019

Вы можете сделать:

const verbose = [{"Key": "Name","Value": "John Doe","Instance": 1},{"Key": "Age","Value": "33","Instance": 1},{"Key": "Child","Value": "Jane","Instance": 1},{"Key": "Child","Value": "Rocky","Instance": 2}];
const concise = Object.values(verbose.reduce((a, {Key, Value}) => (Key === 'Child' ? a.childs[0].Child.push(Value) : a.keys.push({[Key]: Value}), a), {keys: [], childs: [{Child: []}]})).flat(1);

console.log(concise);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...