【问题标题】:Arranging json to match another json template安排 json 以匹配另一个 json 模板
【发布时间】:2019-10-21 13:14:17
【问题描述】:

我正在接收第一个 JSON,我想更改它的结构,以便它与我的第二个 JSON 模板匹配

这是 JSON link,我想将其格式化为 this

这是我到目前为止所做的:

for(i=0;i<json.option.length;i++)
{
    var row=json.option[i];

    if(!option.includes(row.option.option_id))
    {
        option.push({
            option_id:row.option.option_id,
            option_name:row.option.option_name,
            max:row.option.max,
            min:row.option.min,
            value:row.option.value,
            price:row.option.price
        })
    }


    if(!option_group.includes(row.option_group_id))
    {
        option_group.push({
            option_group_id:row.option_group_id,
            option_group_name:row.option_group_name,
            max:row.max,
            min:row.min,
            option:option
        })
    }
}

当数组中已经存在第一个 JSON option.option_group_id 时会出现问题,它不会再添加任何对象。有没有办法做到这一点?

【问题讨论】:

  • 你的第二个链接坏了。
  • 输入中没有Whipped Cream,怎么来的输出?还有,quantity_max 是怎么计算出来的?

标签: javascript arrays node.js json


【解决方案1】:

给定的输入和输出之间存在一些不一致:

  • 输入对象中缺少选项名称“鲜奶油”。
  • 没有说明应该如何更改/计算qtyqty_minqty_max

以下是使用array.reducearray.mapSetObject.assign 的解决方案。进一步的解释可以在下面的代码中找到。

输出的json结构其实是正确的,qtyqty_max应该是按照想要的标准计算出来的,目前不解释。

const input = {
  "item_name": "Drink", 
  "item_id": 1065, 
  "quantity_value": 1, 
  "item_price": 1, 
  "option": [
    {
      "max": 1, 
      "option": {
        "min": 0, 
        "option_name": "Small", 
        "max": 1, 
        "price": 0, 
        "option_id": 3426, 
        "value": 1
      }, 
      "option_group_name": "Size", 
      "option_group_id": "drink_size", 
      "min": 1
    }, 
    {
      "max": 1, 
      "option": {
        "min": 0, 
        "option_name": "Medium", 
        "max": 1, 
        "price": 0, 
        "option_id": 3426, 
        "value": 1
      }, 
      "option_group_name": "Size", 
      "option_group_id": "drink_size", 
      "min": 1
    }, 
    {
      "max": 1, 
      "option": {
        "min": 0, 
        "option_name": "Large", 
        "max": 1, 
        "price": 0, 
        "option_id": 3426, 
        "value": 1
      }, 
      "option_group_name": "Size", 
      "option_group_id": "drink_size", 
      "min": 1
    }, 
    {
      "max": 5, 
      "option": {
        "min": 0, 
        "option_name": "Decaf", 
        "max": 1, 
        "price": 0, 
        "option_id": 3580, 
        "value": 1
      }, 
      "option_group_name": "Extras", 
      "option_group_id": "coffee_extras", 
      "min": 0
    }, 
    {
      "max": 5, 
      "option": {
        "min": 0, 
        "option_name": "Espresso Shot", 
        "max": 1, 
        "price": 30, 
        "option_id": 3581, 
        "value": 1
      }, 
      "option_group_name": "Extras", 
      "option_group_id": "coffee_extras", 
      "min": 0
    }
  ]
};

// Accumulator for the outer max quantity. Assuming it's the sum of all the inner "max" quantities.
let maxQty = 0;
let _groupedOptions = [...new Set(input.option.map(o => o.option_group_id))].reduce((acc, next) => {
  // Acquire the (outer) option for the [next] item, where next is the option_group_id.
  const _filteredOptions = input.option.filter(o => o.option_group_id === next);
  // Max qty of the following options. Assuming it's the sum of the inner quantities. Otherwise, change that.
  let innerMaxQty = _filteredOptions.map(i => +i.max).reduce((a,b) => a + b, 0);
  // Eventual update of the outer max quantity. Eventually change this if the calculation criteria is different.
  maxQty = maxQty < innerMaxQty ? innerMaxQty : maxQty;
  // Acquire the inner options of the looped item.
  const _innerOptions = _filteredOptions.map(o => o.option);
  // Push a new object containing the desired options in the inner option property, by getting the defualt object informations from the outer option group.
  // As a side note, you should not get the _filteredOptions[0], but you should give further explanations about how the master object should calculated the properties, otherwise it's quite vague.
  // After pushing, return the accumulator for the next iteration.
  return acc.push(Object.assign(_filteredOptions[0], {
    option: _innerOptions
  })), acc;
}, []);

// Generate the output by cloning the input object, removing its `option` property, and assigning the calculated option_group property.
// I've also put maxQty, but I'm pretty sure you should give further explanations on how to calculate it, just change it as you need.
const output = Object.assign({}, input, {
  quantity_max: maxQty,
  option_group: _groupedOptions
});
delete output.option;
console.log(output);

【讨论】:

    【解决方案2】:

    这是一个使用 Ramda.js 的解决方案

    const data =  {
        item_id: 1065,
        item_name: "Drink",
        item_price: 1,
        option: [
            {
                max: 1,
                min: 1,
                option: {
                    max: 1,
                    min: 0,
                    option_id: 3426,
                    option_name: "Small",
                    price: 0,
                    value: 1
                },
                option_group_id: "drink_size",
                option_group_name: "Size"
            },
            {
                max: 1,
                min: 1,
                option: {
                    max: 1,
                    min: 0,
                    option_id: 3426,
                    option_name: "Medium",
                    price: 0,
                    value: 1
                },
                option_group_id: "drink_size",
                option_group_name: "Size"
            },
            {
                max: 1,
                min: 1,
                option: {
                    max: 1,
                    min: 0,
                    option_id: 3426,
                    option_name: "Large",
                    price: 0,
                    value: 1
                },
                option_group_id: "drink_size",
                option_group_name: "Size"
            },
            {
                max: 5,
                min: 0,
                option: {
                    max: 1,
                    min: 0,
                    option_id: 3580,
                    option_name: "Decaf",
                    price: 0,
                    value: 1
                },
                option_group_id: "coffee_extras",
                option_group_name: "Extras"
            },
            {
                max: 5,
                min: 0,
                option: {
                    max: 1,
                    min: 0,
                    option_id: 3581,
                    option_name: "Espresso Shot",
                    price: 30,
                    value: 1
                },
                option_group_id: "coffee_extras",
                option_group_name: "Extras"
            }
        ],
        quantity_value: 1
    }
    
    
    const transformGroup = (group) =>
      R.pipe(
        R.mergeAll,
        R.assoc("option", R.pluck("option", group))
      )(group)
      
    const transformOption = (option) => 
      R.pipe(
        R.groupBy(R.prop("option_group_id")),
        R.map(transformGroup),
        R.values,
      )(option)
    
    const transformData = (data) => 
      R.pipe(
        R.assoc("option_group", transformOption(data.option)),
        R.dissoc("option"),
      )(data)
    
    console.log(transformData(data))
    &lt;script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"&gt;&lt;/script&gt;

    【讨论】:

      猜你喜欢
      • 2013-11-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-10
      • 1970-01-01
      • 2016-01-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多