trying to find out how to reformat JSON response and reformat the data
This is a doozie.
I've got the following .json formatted file:
"response": {
"tickets": [
{
"alias": "Lower Box 122",
"curr_price": 16.0,
"quantity": 2,
"seats": "17,18",
},
{
"alias": "Lower Box 122",
"curr_price": 8.0,
"quantity": 5,
"seats": "1,2,3,4,5",
},
{
"alias": "Lower Box 122",
"curr_price": 14.0,
"quantity": 7,
"seats": "6,7,8,9,10,11,12",
},
{
"alias": "Lower Box 123",
"curr_price": 16.0,
"quantity": 2,
"seats": "17,18",
},
{
"alias": "Lower Box 123",
"curr_price": 8.0,
"quantity": 5,
"seats": "1,2,3,4,5",
},
{
"alias": "Lower Box 123",
"curr_price": 14.0,
"quantity": 7,
"seats": "6,7,8,9,10,11,12",
}
]
}
I'm trying to get this output:
Lower Box 122,
quantity: 15,
seats: 1,2,3,4,5,6,7,8,9,10,11,12,17,18,
price: 8-16
Lower Box 123,
quantity: 15,
seats: 1,2,3,4,5,6,7,8,9,10,11,12,17,18,
price: 8-16
Unfortunately, reformatting the original JSON file isn't possible. I've got to deal with开发者_开发技巧 the format that it's currently.
I don't necessarily need it in a .json format again. Spitting out text to a page will be just fine. Can anyone point me to a utility that does just this? or a script that will bang this out?
difficulty: javascript only.
I want to thank everyone that had an answer - hopefully this will come in handy for others.
<script type="text/javascript">
$(document).ready(function () {
var response = {"tickets":[{"alias":"Lower Box 122","curr_price":16.0,"quantity":2,"seats":"17,18",},{"alias":"Lower Box 122","curr_price":8.0,"quantity":5,"seats":"1,2,3,4,5",},{"alias":"Lower Box 122","curr_price":14.0,"quantity":7,"seats":"6,7,8,9,10,11,12",},{"alias":"Lower Box 123","curr_price":16.0,"quantity":2,"seats":"17,18",},{"alias":"Lower Box 123","curr_price":8.0,"quantity":5,"seats":"1,2,3,4,5",},{"alias":"Lower Box 123","curr_price":14.0,"quantity":7,"seats":"6,7,8,9,10,11,12",}]};
var seats = new Array();
var alias = "";
var quantity;
var min_price = 999999;
var max_price = -1;
$.each(response.tickets, function(key, value){
if(value.alias != alias)
{
if(alias != "")
{
seats = seats.sort(function(a,b){ return parseInt(a) > parseInt(b); });
alert(alias + "\ncurr_price: " + min_price + "-" + max_price + "\nquantity: " + quantity + "\nseats: " + seats);
}
alias = value.alias;
quantity = 0;
min_price = 999999;
max_price = -1;
seats = new Array();
}
if(value.curr_price < min_price)
{
min_price = value.curr_price;
}
if(value.curr_price > max_price)
{
max_price = value.curr_price;
}
$.each(value.seats.split(","), function(key, value){
if($.inArray(value, seats) < 0)
{
seats.push(parseInt(value));
}
});
quantity += parseInt(value.quantity);
});
//Call again for last one
seats = seats.sort(function(a,b){ return parseInt(a) > parseInt(b); });
alert(alias + "\ncurr_price: " + min_price + "-" + max_price + "\nquantity: " + quantity + "\nseats: " + seats);
});
</script>
If you're willing to include Underscore.js you could use the reduce
/lfold
method.
I gave it a shot, but I suspect it could be neatened up a little:
_.reduce(x.response.tickets, function(memo, obj){
memo[obj.alias] = memo[obj.alias] || {quantity:0, seats:[]};
memo[obj.alias].maxPrice =
Math.max(memo[obj.alias].maxPrice || obj.curr_price, obj.curr_price);
memo[obj.alias].minPrice =
Math.min(memo[obj.alias].minPrice || obj.curr_price, obj.curr_price);
memo[obj.alias].quantity += obj.quantity;
memo[obj.alias].seats =
memo[obj.alias].seats.concat(_.map(obj.seats.split(","), function(v){
return parseInt(v,10);
}));
memo[obj.alias].seats.sort(function(a,b){return a-b;});
return memo;
}, {})
which leaves you with:
{
"Lower Box 122": {
"quantity": 14,
"seats": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 17, 18],
"maxPrice": 16,
"minPrice": 8
},
"Lower Box 123": {
"quantity": 14,
"seats": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 17, 18],
"maxPrice": 16,
"minPrice": 8
}
}
Additionally, if you'd prefer the result to be an array of objects rather than the hash, you can transform it like this (assuming var k
is the result of the fold above):
_.keys(k).map(function(alias){
k[alias].alias = alias;
return k[alias];
})
Little bit of work required in order to merge those ticket types.
(function($) {
$(document).ready(function() {
var responses = {};
$.getJSON('responsefile.json', function(data) {
$.each(data.response.tickets, function(index, cTicket) {
var cSeats = cTicket.seats.split(/,/);
if (responses[cTicket.alias] == undefined) {
responses[cTicket.alias] = { alias: cTicket.alias,
price: { min: cTicket.curr_price, max: cTicket.curr_price },
quantity: cTicket.quantity,
seats: cSeats };
} else {
var cResponse = responses[cTicket.alias];
$.each(cSeats, function(i, cSeatNumber) {
if ($.inArray(cSeatNumber, cResponse.seats) == -1) {
$.merge(cResponse.seats, [cSeatNumber]);
}
});
cResponse.seats.sort(function(a, b) {
return parseInt(a) - parseInt(b);
});
cResponse.quantity = responses[cTicket.alias].seats.length;
cResponse.price.min = (cTicket.curr_price < cResponse.price.min ? cTicket.curr_price : cResponse.price.min);
cResponse.price.max = (cTicket.curr_price > cResponse.price.max ? cTicket.curr_price : cResponse.price.max);
responses[cTicket.alias] = cResponse;
}
});
var responseSet = [];
$.each(responses, function(index, cResponse) {
responseSet.push(cResponse);
});
responseSet.sort(function(rA, rB) {
return (rA.alias < rB.alias ? -1 : (rA.alias > rB.alias ? 1 : 0));
});
processResponses(responseSet);
});
});
})(jQuery);
As you requested a method of writing out the responses, I have slightly altered the code above to call a function to do on exit. Just adapt this function below to point to the right place.
(function($) {
function processResponses(responses) {
var responseText = '';
var csv = "alias,quantity,seats,price\n";
$.each(responses, function(index, cResponse) {
responseText = responseText
+ cResponse.alias + ",\n"
+ "quantity: " + cResponse.quantity + ",\n"
+ "seats: " + cResponse.seats.join(',') + ",\n"
+ "price: " + cResponse.price.min + (cResponse.price.min == cResponse.price.max ? '' : '-' + cResponse.price.max) + "\n";
csv = csv
+ cResponse.alias + ","
+ cResponse.quantity + ","
+ cResponse.seats.join(' ') + ","
+ cResponse.price.min + (cResponse.price.min == cResponse.price.max ? '' : '-' + cResponse.price.max) + "\n";
});
$('#text-output-location').text(responseText);
$('#csv-output-location').text(csv);
}
})(jQuery);
Note the need to space-separate the seat values in the CSV output, as comma separating them would require a lot of escaping and reduce clarity.
Demo: http://jsfiddle.net/p5QUb/
NB. The demo version has a few modifications to allow the AJAX to take place on jsfiddle.net, which requires special handling, also slight changes to the output to add line breaks.
The following will spit it out in the right format for you:
var obj = { /* your JSON goes here */ };
for (var i=0; i<obj.response.tickets.length; i++) {
document.write(obj.response.tickets[i].alias + ",<br/>");
document.write("quantity: " + obj.response.tickets[i].quantity + ",<br/>");
document.write("seats: " + obj.response.tickets[i].seats + ",<br/>");
document.write("price: " + obj.response.tickets[i].curr_price + "<br/><br/>");
}
I'm not sure how you'd parse that sample output though, since you're separating fields with commas, but one of your values has commas in it, there's an ambiguity there.
Assuming your JSON is parsed into an object called data
, you could just use jQuery:
jQuery.map(data.response.tickets, function(elt) {
var fields = [];
fields.push(elt.alias);
fields.push("quantity:" + String(elt.quantity));
fields.push("price:" + String(elt.curr_price));
fields.push("seats:" + elt.seats);
return fields.join(",\r\n");
}).join("\r\n\r\n");
精彩评论