我很难从下面的数据生成以下格式的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"}
]
在您的示例中,您的对象具有两个相同的键:
"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/
纯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>