从给定数据生成json对象

问题描述 投票:2回答:2

我很难从下面的数据生成以下格式的json对象。 Fiddle

[ { Invoice: 
    { 
       headers: { date: "15-01-2020", buyer: "McDonalds", order: "145632"}, 
       items: { name: "Big Mac",   quantity: "5",  rate: "20.00"}, 
       items: { name: "Small Mac", quantity: "10", rate: "10.00"} 
    } 
  } 
, { Invoice: { // Other invoices go here, I've used just one for this example} } 
] 
<div class="invoice">
  <div class="header">
    <div contenteditable data="date">15-Jan-2020</div>
    <div contenteditable  data="buyer">McDonalds</div>
    <div contenteditable  data="order">145632</div>
  </div>
  <div class="item">
    <div contenteditable data="name">Big Mac</div>
    <div contenteditable data="quantity">5</div>
    <div contenteditable data="rate">20.00</div>
  </div>
  <div class="item">
    <div contenteditable data="name">Small Mac</div>
    <div contenteditable data="quantity">10</div>
    <div contenteditable data="rate">10.00</div>
  </div>
</div>

<button>Loop</button>

jQuery

var button = $("button")
button.on("click",function() {  
  jsonObj =[];
  $('.invoice>.header>div, .invoice>.item>div').each(function(index,item) {
    console.log($(this).parent().attr('class'));
    console.log($(this).attr('data'),$(this).text());
    q = {}
    q ['header'] = $(this).parent().attr('class');
    q [$(this).attr('data')] = $(this).text();

    jsonObj.push(q);
   });
   console.log(jsonObj);
   console.log(JSON.stringify(jsonObj));
});

我最终得到一个像这样的对象,其中的键在各处重复出现。我该如何正确处理?

  [ { "header": "header", "date": "15-Jan-2020"} 
  , { "header": "header", "buyer": "McDonalds"} 
  , { "header": "header", "order": "145632"} 
  , { "header": "item", "name": "Big Mac"} 
  , { "header": "item", "quantity": "5"} 
  , { "header": "item", "rate": "20.00"} 
  , { "header": "item", "name": "Small Mac"} 
  , { "header": "item", "quantity": "10"} 
  , { "header": "item", "rate": "10.00"} 
  ] 
javascript jquery json
2个回答
2
投票

在您的示例中,您的对象具有两个相同的键:

"items":{
    "name":"Big Mac",
    "quantity":"5",
    "rate":"20.00"
}
"items":{
    "name":"Small Mac",
    "quantity":"10",
    "rate":"10.00"
}

这将不起作用,因为您只能有一个,所以您需要将items键的值更改为对象数组:

"items":[
    {
        "name":"Big Mac",
        "quantity":"5",
        "rate":"20.00"
    },
    {
        "name":"Small Mac",
        "quantity":"10",
        "rate":"10.00"
    }
]

迭代代码可能看起来像这样:

const jsonObj = [];

$('.invoice').each((index, item) => {
 const invoice = {
    header: {},
    items: []
 };

 $(item).find('.header > div').each((index, item) => {
    const key = $(item).attr('data');
    invoice.header[key] = $(item).text();
 });

 $(item).find('.item').each((index, item) => {
    const itemObj = {};

    $(item).find('div').each((index, item) => {
        const key = $(item).attr('data');
        itemObj[key] = $(item).text();
    });

    invoice.items.push(itemObj);
 });

 jsonObj.push({
    Invoice: invoice
 });
});

与您的版本的主要区别在于,它会逐步遍历dom。首先,通过每个发票,然后通过发票的每个抬头和每个项目。这样就很容易构建所需的结构。

这是jsfiddle链接:https://jsfiddle.net/tara5/tanb174h/


1
投票

纯JS代码:

const jsonObj  = []
  ,   inVoices = document.querySelector('.invoice')
  ,   subDivOf = (parent,query) => [...parent.querySelectorAll(query)]
  ,   dataElms = (ac,el)=>{ac[el.getAttribute('data')]=el.textContent;return ac }
  ;

Loop.onclick=_=>
  {
  jsonObj.push(getInVoicesValues())
  console.clear()
  console.log( jsonObj )
  }
function getInVoicesValues() 
  {
  const headers  = subDivOf(inVoices,'.header>div').reduce(dataElms,{})
    ,   items    = subDivOf(inVoices,'.item').reduce((accI,itm)=>
                      {
                      accI.push( subDivOf(itm, 'div').reduce(dataElms,{}))
                      return accI
                      },[])
      ;
  return { headers, items }      
  }
<div class="invoice">
  <div class="header">
    <div contenteditable data="date">15-Jan-2020</div>
    <div contenteditable data="buyer">McDonalds</div>
    <div contenteditable data="order">145632</div>
  </div>
  <div class="item">
    <div contenteditable data="name">Big Mac</div>
    <div contenteditable data="quantity">5</div>
    <div contenteditable data="rate">20.00</div>
  </div>
  <div class="item">
    <div contenteditable data="name">Small Mac</div>
    <div contenteditable data="quantity">10</div>
    <div contenteditable data="rate">10.00</div>
  </div>
</div>
    
<button id="Loop">Loop</button>

[第二方法]

const jsonObj = [];
const Elms    = document.querySelectorAll('.invoice div');

Loop.onclick=_=>
  {
  jsonObj.push(getValues())
  console.clear()
  console.log( jsonObj )
  }
function getValues() 
  {
  let rep  = { headers:{}, items:[] }
    , cur  = null
    ;
  Elms.forEach(el=>
    {
    switch (true)
      {
      case (el.matches('.header')):
        cur = rep.headers;
        break;
      case (el.matches('.item')):
        cur = {}
        rep.items.push(cur);
        break;
      default:  // (el.matches('[contenteditable]'))
        cur[el.getAttribute('data')]=el.textContent
        break;
      }
    })
  return rep
  }
<div class="invoice">
  <div class="header">
    <div contenteditable data="date">15-Jan-2020</div>
    <div contenteditable data="buyer">McDonalds</div>
    <div contenteditable data="order">145632</div>
  </div>
  <div class="item">
    <div contenteditable data="name">Big Mac</div>
    <div contenteditable data="quantity">5</div>
    <div contenteditable data="rate">20.00</div>
  </div>
  <div class="item">
    <div contenteditable data="name">Small Mac</div>
    <div contenteditable data="quantity">10</div>
    <div contenteditable data="rate">10.00</div>
  </div>
</div>
    
<button id="Loop">Loop</button>
© www.soinside.com 2019 - 2024. All rights reserved.