I want to transform a SQLite Database into a JSON object. After searching the web I decided to write a function by myself. I'm still a beginner in JS/JSON/jQuery and I thought the following code should work:
function sqlite2json(){
newJson = '{ "$resources": [';
offlinedb = openDatabase (shortName, version, displayName, maxSize);
offlinedb.transaction(function(transaction) {
transaction.executeSql('SELECT * FROM Zaehlliste;', [],
function(transaction, result) {
if (result != null && result.rows != null) {
for (var k = 0; k < result.rows.length; k++) {
var row = result.rows.item(k);
newJson += '{ "Field0":"' + row.Field0 + '", "Field1":"' + row.Field1 + '", "Field2":"' + row.Field2 + '", "Field3":"' + row.Field3 + '", "Field4":"' + row.Field4 + '", "Field5":"' + row.Field5 + '"},'
}
jsonall = newJson + ']}';
alert(jsonall); //shows me a correct JSON as string
jsonobjoff = $.parseJSON(jsonall);
for (i = 0; i < jsonobjoff.$resources.length; i++) {
$('#json').append("<li>" + jsonobjoff.$resources[i].Field0 + " " + jsonobjoff.$resources[i].Field1 + " " + jsonobjoff.$resources[i].Field2 + " " + jsonobjoff.$resources[i].Field3 + " " + jsonobjoff.$resources[i].Field4 + " " + jsonobjoff.$resources[i].Field5 + "</li>");
}
}
},errorHandler);
},errorHandler, nullHandler);
}
This second for-loop and putting content into that element with its id="json" is just to control, that I finally got a true JSON object, but unfortunately there is no list appearing. The alert after declaring jsonall shows me a correct JSON-Object as a string. I think that parseJSON is not working, but I have no clue, why it is not working. Could it be that comma after the last entry of the JSON-Object? I know this is not clean, but it should still work...?
the json you generate is incorrect.
you add a trailing comma after every object (in your first for loop), but the last entry shouldn't add a comma, or it isnt valid json.
change this:
newJson += '{ "Field0":"' + row.Field0 + '", "Field1":"' + row.Field1 + '", "Field2":"' + row.Field2 + '", "Field3":"' + row.Field3 + '", "Field4":"' + row.Field4 + '", "Field5":"' + row.Field5 + '"},';
to:
if(k > 0) newJson += ',';
newJson += '{ "Field0":"' + row.Field0 + '", "Field1":"' + row.Field1 + '", "Field2":"' + row.Field2 + '", "Field3":"' + row.Field3 + '", "Field4":"' + row.Field4 + '", "Field5":"' + row.Field5 + '"}';
that will work (if you dont have special characters in your strings)
i would recommend that you use this json encoder instead of manually generating the string, it will handle special characters too, which yours will have problems with: https://github.com/douglascrockford/JSON-js/blob/master/json2.js
code for this:
change newJson = '{ "$resources": ['; to newJson = { $resources: [] };
and in the loop:
newJson.$resources[k] = { Field0: row.Field0, Field1: row.Field1, Field2: row.Field2, Field3: row.Field3, Field4: row.Field4, Field5: row.Field5 };
you could just use newJson.$resources[k] = row; here, but if row has more Fields that you dont want to show, they will be taken too
create the json string:
jsonall = JSON.stringify(newJson);
Related
The script doesn't throw any errors, but rarely completely works - i.e. complete successfully with all of the expected data in the destination tab. The results breakdown is generally:
no results in the destination sheet - this happens ~50-75% of the time
all of the results in the destination sheet, except in cell A1 - ~25% of the time
100% completely works - ~15-25% of the time
code snippet of the batchupdate() call
var data = [
{
range: (ss.getSheetName() + "!A1:AQ" + valueArray.length)
,values: valueArray
}
];
const resource = {
valueInputOption: "RAW"
,data: data
};
Logger.log("request = " + JSON.stringify(resource)
+ "\n" + "valueArray = " + valueArray.length
);
Logger.log(" Sheets.Spreadsheets.Values.batchUpdate(params, batchUpdateValuesRequestBody) ");
var response = Sheets.Spreadsheets.Values.batchUpdate(resource, spreadsheetId);
Logger.log("response = " + response.toString());
and the response
response = {
"totalUpdatedRows": 37776,
"responses": [{
"updatedCells": 1482389,
"updatedRange": "BatchUpdateDestination!A1:AP37776",
"updatedColumns": 42,
"spreadsheetId": "adahsdassadasdsadaasdasdasdasdasdasdasdasdas",
"updatedRows": 37776
}
],
"spreadsheetId": "adahsdassadasdsadaasdasdasdasdasdasdasdasdas",
"totalUpdatedCells": 1482389,
"totalUpdatedSheets": 1,
"totalUpdatedColumns": 42
}
Its obviously a very large dataset, but I've pruned the destination spreadsheet to ensure there is ample room for the data, and from earlier testing, I believe that a specific size error would be returned if that was the blocker.
How can I troubleshoot, or better yet, prevent these incomplete executions? is there any way to inspect the batch jobs that these requests initiate?
Answering my own question...
After toiling with this a little more, I couldn't figure out any way to troublshooting or inspect the odd, seemingly successfully batchUpdate() jobs. Thus, I resorted to batching the batchUpdate() calls into batches of 15000. This seems to work consistently, though maybe a bit slower:
// This is the very large 2D array that is populated elsewhere
var valueArray = [];
var maxRows = valueArray.length;
var maxCols = valueArray[0].length;
var batchSize = 15000;
var lastBatchSize = 1;
for (var currentRowCount = 1; currentRowCount <= maxRows; ++currentRowCount) {
if( currentRowCount % batchSize == 0
|| currentRowCount == maxRows
)
{
Logger.log("get new valuesToSet");
valuesToSet = valueArray.slice(lastBatchSize - 1, currentRowCount -1);
var data = [
{
range: (ss.getSheetName() + "!A" + lastBatchSize + ":AQ" + (lastBatchSize + valuesToSet.length))
,values: valuesToSet
}
];
const resource = {
valueInputOption: "RAW"
,data: data
};
Logger.log("request = " + JSON.stringify(resource).slice(1, 100)
+ "\n" + "valuesToSet.length = " + valuesToSet.length
);
try {
var checkValues = null;
var continueToNextBatch = false;
for (var i = 1; i <= 3; ++i) {
Logger.log("try # = " + i
+ "\n" + " continueToNextBatch = " + continueToNextBatch
+ "\n" + " make the batchUpdate() request, then sleep for 5 seconds, then check if there are values in the target range."
+ "\n" + " if no values, then wait 5 seconds, check again."
+ "\n" + " if still not values after 3 tries, then resubmit the batchUpdate() requestion and recheck values"
+ "\n" + "range to check = " + "A" + lastBatchSize + ":AQ" + lastBatchSize
);
Logger.log(" Sheets.Spreadsheets.Values.batchUpdate(params, batchUpdateValuesRequestBody) ");
var response = Sheets.Spreadsheets.Values.batchUpdate(resource, spreadsheetId);
Logger.log("response = " + response.toString());
/// loop and check for data in newly written range
for (var checks = 1; checks <= 3; ++checks) {
Utilities.sleep(5000);
var checkValues = ss.getRange(("A" + lastBatchSize + ":AQ" + lastBatchSize)).getValues();
Logger.log("new cell populated - checks # = " + checks
+ "\n" + "range to check = " + "A" + lastBatchSize + ":AQ" + lastBatchSize
+ "\n" + "checkValues.length = " + checkValues.length
+ "\n" + "checkValues = " + checkValues
);
if(checkValues.length > 1)
{
Logger.log("checkValues.length > 1, so continue to next batch"
+ "\n" + "range to check = " + "A" + lastBatchSize + ":AQ" + lastBatchSize
+ "\n" + "checkValues.length = " + checkValues.length
+ "\n" + "checkValues = " + checkValues
);
continueToNextBatch = true;
continue;
}
else
{
Logger.log("checkValues.length is still not > 1, so try the request again"
+ "\n" + "range to check = " + "A" + lastBatchSize + ":AQ" + lastBatchSize
);
}
}
if(continueToNextBatch)
{
continue;
}
}
}
catch (e) {
console.error("range.setValues(valuesToSet) - yielded an error: " + e
+ "\n" + "valuesToSet = " + valuesToSet.length
+ "\n" + "maxRows = " + maxRows
+ "\n" + "maxCols = " + maxCols
+ "\n" + "currentRowCount = " + currentRowCount
+ "\n" + "current range row start (lastBatchSize) = " + lastBatchSize
+ "\n" + "current range row end (j - lastBatchSize) = " + (currentRowCount - lastBatchSize)
);
}
lastBatchSize = currentRowCount;
}
}
Here is my JSON
var gal = [
{
"folder":"nu_images",
"pic":"gd_42.jpg",
"boxclass":"pirobox_gall",
"alt":"Rand Poster 1",
"title":"Rand Poster 1",
"thfolder":"th",
"thumbpic":"th_gd_42.jpg"
},
{
"folder":"nu_images",
"pic":"gd_13.jpg",
"boxclass":"pirobox_gall",
"alt":"Explosive Pixel Design",
"title":"Explosive Pixel Design",
"thfolder":"th",
"thumbpic":"th_gd_13.jpg"
}
];
and here is my for loop
for (i = 0; i < gal.length; i++) {
document.getElementById("gallery").innerHTML = "" + "<img src=\"" + "http:\/\/galnova.com\/" + gal[i].folder + "\/" + "th\/" + gal[i].thumbpic + "\"" + "border=\"0\"" + "alt=\"" + gal[i].alt + "\"" + "title=\"" + gal[i].title + "\"\/>" + ""
};
I am trying to make my JSON show all of the objects in HTML one after the other. I can get it to show the first one or whatever number I put into the array but I don't know how to make it generate a list of them.
Here is a link to my jsfiddle. Any help you can offer would be greatly appreciated.
http://jsfiddle.net/o7cuxyhb/10/
It's being generated here <p id="gallery"></p> just not correctly.
You're overwriting your html with every loop iteration:
document.getElementById("gallery").innerHTML = ...
^---
Perhaps you want something more like
document.getElementById("gallery").innerHTML += ...
^---
which will concatenation the original html contents with your new stuff.
And technically, you shouldn't be doing this in a loop. Changing .innerHTML like that causes the document to be reflowed/re-rendered each time you change .innerHTML, which gets very expensive when you do it in a loop. You should be building your html as a plain string, THEN adding it to the dom.
e.g.
var str = '';
foreach(...) {
str += 'new html here';
}
document.getElementById("gallery").innerHTML += str;
for (i = 0; i < gal.length; i++) {
document.getElementById("gallery").innerHTML += "" + "<img src=\"" + "http:\/\/galnova.com\/" + gal[i].folder + "\/" + "th\/" + gal[i].thumbpic + "\"" + "border=\"0\"" + "alt=\"" + gal[i].alt + "\"" + "title=\"" + gal[i].title + "\"\/>" + "" };
Add a += instead of an = after innerHTML
Try this:
function displayJson(jsonArray){
var container = document.getElementById("gallery");
for (var i=0; i<jsonArray.length; i++){
var newElement = document.createElement("a").innerHTML = jsonToHtml(jsonArray[i])
container.appendChild(newElement);
}
}
function jsonToHtml(jsonObj){
//Define your dom object here
var el = document.createElement("a").innerHTML = '' // you code here
...
return el;
}
displayJson(gal);
I'm currently working on a project where I need to convert some older code into a json object. We're taking the result set from a sql query and returning the categories it gives back as json. I'm not that well versed in javascript let alone json so I'm not sure what's the simplest way to go about this. Here is the function I need to change into JSON:
function createOutputCategories(){
try
{
output =
"<html>" +
"<head>" +
"<title>" +
"You can find it!" +
"</title>" +
"</head>" +
"<body bgcolor='#CED3F3'>" +
"<a href='" + url + "file.xsjs?parent=1'>" +
"</a>" +
"<br><br>";
if(parent === "1"){
output = output + "<h3><font color='#AAAAAA'>Home</font>";
}else{
output = output +"<a href='javascript:history.back()'>" +
"<h3>Back";
}
output = output +
"</h3>" +
"</a>" +
"<h1>" +
"Categories:" +
"</h1>";
while(rs.next()){
if(rs.getString(3) === 0 || rs.getString(3) === null || rs.getString(3) === undefined || rs.getString(3) === "0" ){
output = output + "<br><a href='" + url + "yeti.xsjs?parent=" + rs.getString(1) + "'>" + rs.getString(2) + "</a>";
}else{
output = output + "<br><a href='" + url + "yeti.xsjs?parent=" + rs.getString(1) + "'>" + rs.getString(3) + "</a>";
}
}
}catch(Exception){
$.response.contentType = "text/plain";
$.response.setBody( "Failed to retreive data" );
$.response.status = $.net.http.INTERNAL_SERVER_ERROR;
}
Here is what I have so far but I am not returning a valid JSON object:
function createOutputCategories(){
try{
output =
"category: {name = \"" + parent + "\"; description = \"\"}";
output = output +
"subcategories: [ ";
while(rs.next()){
output = output +
"{ catid = \"" + rs.getString(1) + "\"; catname = \"" + rs.getString(2) + "\"; altname = \"" + rs.getString(3) + "\"; description = \"" + rs.getString(4) + "\"}";
}
output = output +
"];";
}
catch(Exception){
$.response.contentType = "text/plain";
$.response.setBody( "Failed to retreive data" );
$.response.status = $.net.http.INTERNAL_SERVER_ERROR;
}
If I need to provide anything else please let me know! Thanks!
Do you want to output a javascript object to a string?
Construct the object:
var category=new Object();
category.name="Name";
category.description="My lovely description";
category.subcategories=[];
var subCat=new Object();
subCat.catid=1;
subCat.catname="My subcat";
category.subcategories.push(subCat);
Alternatively, you could construct the object using literals:
var category={
name:"Name",
description:"My lovely description",
subcategories:[
{catid:1,catname:"My subcat"}
]
};
Then return the object as string.
return JSON.stringify(category);
A reference to Javascript objects if you need more help:
http://www.w3schools.com/js/js_objects.asp
I've been working with highcharts and MVC 3 for two years by now (I never done anything complicated, just load data and make it work stuff), and I worked with two different scenarios:
Chart code written in the directly in the view, loading data through Json
Html helper responsible to plot the chart
The Html helper approach seems to me a more elegant choice ... but then, just to illustrate to you guys, here is how it looks like (just part of it):
public static string DisplayChart(
this HtmlHelper helper,
ChartOptions options,
TimedChartSeries[] data)
{
string[] axisList = data.GroupBy(t => t.Unit).Select(t => t.Key).ToArray();
string result = "";
result += "<script type=\"text/javascript\">\n";
result += "var " + options.ChartName + ";\n";
result += "$(document).ready(function() {\n";
result += options.ChartName + "= new Highcharts.Chart({\n";
result += "chart: {renderTo: '" + options.DivName + "',zoomType: ''},\n";
result += "title: { text: '" + options.Title + "'},\n";
result += "subtitle: {text: '" + options.SubTitle + "'},\n";
result += "xAxis: { type: 'datetime'," +
"\n dateTimeLabelFormats: {month: '%e. %b', year: '%b' },"
+ "labels:{rotation: -45}\n},\n";
string axes = "";
for (int i = 0; i < axisList.Length; i++)
{
var temporaryData = data.First(t => t.Unit == axisList[i]);
if (i != 0)
axes += ", ";
axes += "{labels:{\n " +
"formatter : function(){return this.value + '" + temporaryData.Unit + "';},\n" +
"style:{color:'#" + temporaryData.Color.Name.Remove(0, 2) + "'}},\n" +
"title:{text:'',style:{color:'#" + temporaryData.Color.Name.Remove(0, 2) + "'}},\n" +
"}\n";
}
result += "yAxis: [\n" + axes + "],\n";
string units = "";
for (int i = 0; i < data.Length; i++)
{
if (i != 0)
units += ", ";
units += "'" + data[i].Title + "': '" + data[i].Unit + "'\n";
}
result += "tooltip:{\nshared: true,\n backgroundColor: 'none' ,\nborderColor: 'none'," +
"\nshadow:false\n ,crosshairs: true,\n" +
"formatter: function() {var s = '<table class=\"table-list\"><tr><th>Hora</th><th>'+ test(this.x) +'</th></tr>';" +
"\n$.each(this.points, function(i, point) {" +
"\ns += '<tr><td>'+point.series.name + '</td><td>'+point.y+'</td></tr>'});s+='</table>';" +
"\n$('#tooltip').html(s);}},";
result += "lang: {" +
"months: ['Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho'," +
"'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro']," +
"weekdays: ['Domingo', 'Segunda', 'Terça', 'Quarta', 'Quinta', 'Sexta', 'Sábado']},";
string series = "";
int x = 0;
for (int j = 0; j < axisList.Length; j++)
{
var temporaryData = data.Where(t => t.Unit == axisList[j]).ToArray();
for (int i = 0; i < temporaryData.Length; i++)
{
if (x > 0)
series += ", ";
series += "{name: '" + temporaryData[i].Title + "',\n color: '#" + temporaryData[i].Color.Name.Remove(0, 2) +
"', \ntype: '" + temporaryData[i].Type + "',\nunit:'" + temporaryData.First().Unit + "', \nyAxis:" + j + " , \ndata:[" + FromArrayToString(temporaryData[i].Data) +
"], marker: { enabled: false}}\n";
x++;
}
}
result += "series: [\n" + series + "]\n";
result += "});});";
result += "\nfunction test(i)\n{\nvar j = new Date(i + 2*60*60*1000);\n" +
"return new Date(i + 3*60*60*1000).format('d/m/Y H:i:s.')+j.getMilliseconds();\n}\n</script>";
result += "\n<div id=\"" + options.DivName + "\" style=\"width:" + options.Width + ";height: " + options.Height + "\"></div>" +
"<div id=\"tooltip\"></div>";
return result;
}
It's really simple to call this helper:
#Html.Raw(Html.DisplayChart((ChartOptions)Model.Options,(TimedChartSeries[])Model.Series))
As you guys can see, I have to use the Html.Raw helper in order to make it work ... that is problem nº 1 (and it probably has an easy solution). But the second problem is really great: the chart becomes entirely tied to my domain. If I wanted to plot a, say, bar chart displaying data of the last 3 years in months (each month being represented by a bar), it would be impossible to use this helper.
And it also looks kind of ugly.
So, guys, which option do you think is more elegant, the Json or the Helper approach?
About the use of Html.Raw and the easy solution:
Change your function to
public static HtmlString DisplayChart(this HtmlHelper helper, ...)
{
...
return new HtmlString(result);
}
You then may use #Html.DisplayChart(...) in your razor views.
Also, please make sure that options.DivName, options.Title, options.SubTitle etc. are properly escaped - a title like Everybody's favorite chart will break the output.
I am displaying table rows in the form. Each row has 5 columns, one of the columns is an (editable) textbox field.
ajaxLoading(true);
$.post('<%=request.getContextPath()%>'+"/processServlet", postData,
function(data) {
var ctxPath='<%=request.getContextPath()%>';
currentPosition = data.currentPosition;
var items = $("#itemsTable");
items.empty();
if (data.items.length == 0) {
items.append($('<tr><td colspan=5 style="color:red;">No items<td></tr>'));
}
;
for (var i = 0; i < data.items.length; i++) {
editText = "";
items.append($("<tr " + zebra + "><td><a href=\"javascript: deviceView('" + data.items[i].id + "')\">" + data.items[i].num +
"</a></td><td>" + data.items[i].itemType +
"</td><td><input type = 'checkbox' id = 'CheckBoxRow_' />" + data.items[i] +
"</td><td><input type = 'textbox' id = 'TextBoxRow_' value = '" + data.items[i].itemName +"' "/>" +
"</td><td>" + data.items[i].status +
"</td><td>" + data.items[i].date + "</td>" +
"<td>" + data.items[i].firmware + "<td>" +
"Delete" +
"</tr>"));
;
ajaxLoading(false);
}, "json");
How do I auto select the check box when the data is entered or modified in the textbox and save the data in the database?
bind to textbox onchange event and have it set the checkbox to checked=true once returned with a value (and not already checked).
$('#itemsTable input[type="checkbox"]').change(function(e){
var $cb = $(this);
if ($cb.is(':checked')){
$cb.closest('tr').find('input[type="checkbox"][id^=CheckBoxRow_]').prop('checked','true');
}
});
basically. though you really should not use HTML in an append, and should be building the objects with jQuery.