2016-07-28 4 views
0

Как преобразовать (без сложных циклов foreach), если возможно, с существующими JS-библиотеками (RxJS для Observables, Lodash/Underscore/безотносительно)Преобразование вложенного JSON в плоский JSON с использованием TypeScript/JS/RxJS/map/reduce/filter any,

следующую структуру:

{ 
    "result": [ 
     { 
      "content": { 
       "resources": [ 
        { 
         "prop": [ 
          { 
           "key": "BAR", 
           "value": "Bar getting better" 
          }, 
          { 
           "key": "FOO", 
           "value": "Foo is cool" 
          } 
         ] 
        } 
       ] 
      } 
     } 
    ] 
} 

в этот Исли?

{ 
    "BAR": "Bar getting better", 
    "FOO": "Foo is cool" 
} 

ответ

1

В Lodash, используйте _.keyBy и затем _.mapValues

var data = {"result":[{"content":{"resources":[{"prop":[{"key":"BAR","value":"Bar getting better"},{"key":"FOO","value":"Foo is cool"}]}]}}]}, 
 
    input = data.result[0].content.resources[0].prop; 
 

 
var result = _.mapValues(_.keyBy(input, 'key'), 'value'); 
 

 
console.log(result);
<script src="https://cdn.jsdelivr.net/lodash/4.13.1/lodash.min.js"></script>

+0

большое спасибо, ..Возможно, еще один вопрос: как я могу преобразовать его обратно в большую структуру? –

+1

'_.map (obj, function (v, k) {return {key: k, value: v}})' – 4castle

+1

Или '_.map (obj, (v, k) => ({key: k, value: v})) ' – 4castle

1

Для этой конкретной структуры данных вы можете использовать reduce() и вернуть объект.

var data = {"result":[{"content":{"resources":[{"prop":[{"key":"BAR","value":"Bar getting better"},{"key":"FOO","value":"Foo is cool"}]}]}}]} 
 

 
var result = data.result[0].content.resources[0].prop.reduce(function(r, e) { 
 
    r[e.key] = e.value; 
 
    return r; 
 
}, {}); 
 

 
console.log(result);

ES6 версия с функцией стрелки

var data = {"result":[{"content":{"resources":[{"prop":[{"key":"BAR","value":"Bar getting better"},{"key":"FOO","value":"Foo is cool"}]}]}}]} 
 
var ar = data.result[0].content.resources[0].prop; 
 

 
var result = ar.reduce((r, e) => (r[e.key] = e.value, r), {}); 
 
console.log(result);

+0

Это массив объектов. – 4castle

+0

@ 4castle Исправлено. –

+0

Функция стрелки не нуждается в 'return'. Просто используйте '(r, e) => (r [e.key] = e.value, r)' – 4castle

0

Это решение с ванильным Javascript ES6 но это немного сложнее (я не проверял):

var data = ... 
var resultData = {} 

data.result.forEach(result => result.content.resources.forEach(resource => resource.prop.forEach(prop => resultData[prop.key] = prop.value))) 

Или если у вас есть только один элемент для массивов верхнего уровня, то попробуйте это что Javascript ES5:

var data = ... 
var resultData = {} 

data.result[0].content.resources[0].prop.forEach(function(prop) { 
    resultData[prop.key] = prop.value 
}); 
0

Проблема с другими решениями здесь либо

  1. Они выбирают массив в data.result[0].content.resources[0].prop, который не принимает во внимание, что оба result и resources массивов могут быть длиной большей, что один.
  2. Вложенные forEach трудно читать и рассуждать.

Чтобы помочь с этим, я создал небольшую библиотеку deep-reduce, которая поможет вам уменьшить/развязать значения внутри глубоко вложенных объектов. deep-reduce похож на Array.prototype.reduce, хотя он глубоко пересекает вложенные объекты/массивы.

На ваших данных, вы можете использовать его как этот

// if path is ending in prop.number, 
// then `item` is the object we want to untangle 
let untanglePropItems = (reduced, item, path) => { 
    if (path.match(/prop\.\d+$/)) { 
    reduced[item.key] = item.value 
    } 
    return reduced 
} 

// the reduced value is returned 
let reduced = deepReduce(deepNestedObject, untanglePropItems) 

Here is a demo in RunKit.

 Смежные вопросы

  • Нет связанных вопросов^_^