Formatting JSON Data with ColdFusion for HighCharts - json

So I'm working on a pie chart using HighSlide and ColdFusion.
To make this simple, for the data it expects a string like this:
data: [{name: 'Jane',y: 13}, {name: 'John',y: 23}, {name: 'Joe',y: 19}]
What i've done to accomplish this is to loop through my query results and create a string like this:
<cfloop query="getAreaCounts">
<cfset areaList = listAppend(areaList, "{name: '#name#',y: #y#}")>
</cfloop>
I know there has to be an easier/smarter way right? Since this is JSON data, i figured I could just do this:
<cfoutput>#SerializeJSON(getAreaCounts)#</cfoutput>
But that returns a JSON string like this which highcharts won't process:
{"COLUMNS":["Y","NAME"],"DATA":[[8,"Area1"],[7,"Area2"],[1,"Area3"],[1,"Area4"]]}
Any help pointing me in the right direction would be great. Do I need to dig deeper into a JSON - howto?

You're going to want to convert the query to an array of structs and then run serializeJSON() on that array.
Below is a method that I use pretty frequently when working with a lot of queries and JSON. I think that I got it from Ben Nadel's site and then converted it to cfscript.. I'll try to track down the blog post after I post this answer.
public array function queryToArray( required query qry ) {
var columns = arguments.qry.getColumnNames();
var ofTheJedi = [];
for( var i = 1; i LTE qry.recordCount; i++ ) {
var obj = {};
for( var k = 1; k LTE arrayLen( columns ); k++ ) {
structInsert( obj, columns[ k ], arguments.qry[ columns[ k ] ][ i ] );
}
arrayAppend( ofTheJedi, obj );
}
return ofTheJedi;
}
So, in your case you would do something like this:
<cfset myJSON = queryToArray( getAreaCounts ) />
<cfoutput>#serializeJSON( myJSON )#</cfoutput>
EDIT: Here's Ben's blog post that inspired the method above: http://www.bennadel.com/blog/124-Ask-Ben-Converting-a-Query-to-an-Array.htm

You need something like this (untested but you get the idea)
<cfscript>
data = [{name='Jane',y=13],{name='John',y=23},{name='Joe',y=19}];
</cfscript>
<cfoutput>#serializeJson(data)#</cfoutput>
You need to create a Coldfusion array of strucutres (each with "name" and "y" as members).. then serialize it. What you are serializeing above is the query object. By your code it looks like you meant to serialze the "arealist" variable - but that var would probably not come out correct either because it is not an array of structures - it is a list of strings.

Related

Query for nested JSON property in azure CosmosDb

I am having some difficulty crafting a query for nested data in cosmosDB.
Say I have data stored in this structure:
{
id:"1234",
data:{
people:{
"a826bbc5-add9-42d8-ba52-f5de52973556":{
first_name: "Kyle"
},
"efb119d-9f12-4d11-a7e1-38e4719a699c":{
first_name: "Bob"
},
"b402faac-d1ba-4317-9ba6-673c76a8fc37":{
first_name: "Jane"
}
}
}
}
Now I want to write a query that would return all of the people with the first name of "Bob"
I need something like:
Select * from c where c.data.people[*].first_name = "Bob";
Notice that the "people" object is an actual JSON object not a JSON array, so no array_contains, I need basically the JSON obj equivalent.
I've looked around and can't seem to find the appropriate query for this common use-case.
Anyone know how I can accomplish this query?
Since the key of people objects is random,i'm afraid you can't query it with normal sql.I tried to implement your needs with UDF in cosmos db.
Udf code:
function userDefinedFunction(peopleObj){
var returnArray = [];
for(var key in peopleObj){
if (peopleObj[key].first_name == "Bob"){
var map = {};
map[key] = peopleObj[key];
returnArray.push(map);
}
}
return returnArray;
}
Sql:
SELECT udf.test(c.data.people) as BobPeople FROM c
Sample data:
Output:
Marked Jay's answer as the accepted answer as I ended up using udfs - I'll post the function I ended up using and the query for anyone looking for something a little more generic.
function userDefinedFunction(properties, fieldName, filedValue){
for(var k in properties){
if(properties[k][fieldName] && properties[k][fieldName] == filedValue)
return true;
}
return false;
}
with a query of:
select * from c where udf.hasValue(c.data.people,"first_name","Bob")

NodeJS: Adding new child nodes to JSON Object

lets say there is customer object, i need to add new element address to this json object customer. how can I achieve this?
Both of these are not altering the customer JSON object
customer['address'] = addressObj
customer.address = addressObj
and I can not use push() as this is not adding a new item in list of objects.
Thanks,
Naren
Maybe your addressObj is not properly formed.
This works for me:
var customer = {"name": "Naren"};
customer.address1 = "stackoverflow";
customer.address2 = {"fulladdress":"stackoverflow"};
JSON.stringify(customer)
Output:
"{"name":"Naren","address1":"stackoverflow","address2":{"fulladdress":"stackoverflow"}}"
Maybe I am not clear on what exactly you want to do but it sounds to me as if you want have a JSON and want to merge it with another JSON, creating just a JSON file.
let Json1 = {'Superman': 'Favorite' };
let Json2 = {'Supergirl': 'Greatest'};
let Json3 = {'IronFist': 'Top 10' };
You now want to add Supergirl (the new element) to Superman (the old element) I assume. Take a look here # merge-json a simple package which does its job well. You would code as follows:
use strict;
var mergeJSON = require("merge-json");
let Json1 = {'Superman': 'Favorite' };
let Json2 = {'Supergirl': 'Greatest'};
let Json3 = {'IronFist': 'Top 10' };
let Json6 = mergeJSON(Json1,Json2);
Json6=mergeJSON(Json6,Json3);
You would end up with as follows:
Json6 = {'Superman': 'Favorite', 'Supergirl': 'Greatest', 'IronFist': 'Top 10'}
This is how I make use of combining JSON information or text information into a JSON file. You can get much more sophisticated with the module mentioned above. (Just do not confuse merge-json with json-merge and other modules.)
If this is not what you are looking for my apologies, then I did not understand the question correctly.

Regular expression to extract a JSON array

I'm trying to use a PCRE regular expression to extract some JSON. I'm using a version of MariaDB which does not have JSON functions but does have REGEX functions.
My string is:
{"device_types":["smartphone"],"isps":["a","B"],"network_types":[],"countries":[],"category":["Jebb","Bush"],"carriers":[],"exclude_carriers":[]}
I want to grab the contents of category. I'd like a matching group that contains 2 items, Jebb and Bush (or however many items are in the array).
I've tried this pattern but it only matches the first occurrence: /(?<=category":\[).([^"]*).*?(?=\])/g
Does this match your needs? It should match the category array regardless of its size.
"category":(\[.*?\])
regex101 example
JSON not a regular language. Since it allows arbitrary embedding of balanced delimiters, it must be at least context-free.
For example, consider an array of arrays of arrays:
[ [ [ 1, 2], [2, 3] ] , [ [ 3, 4], [ 4, 5] ] ]
Clearly you couldn't parse that with true regular expressions.
See This Topic:
Regex for parsing single key: values out of JSON in Javascript
Maybe Helpful for you.
Using a set of non-capturing group you can extract a predefined json array
regex answer: (?:\"category\":)(?:\[)(.*)(?:\"\])
That expression extract "category":["Jebb","Bush"], so access the first group
to extract the array, sample java code:
Pattern pattern = Pattern.compile("(?:\"category\":)(?:\\[)(.*)(?:\"\\])");
String body = "{\"device_types\":[\"smartphone\"],\"isps\":[\"a\",\"B\"],\"network_types\":[],\"countries\":[],\"category\":[\"Jebb\",\"Bush\"],\"carriers\":[],\"exclude_carriers\":[]}";
Matcher matcher = pattern.matcher(body);
assertThat(matcher.find(), is(true));
String[] categories = matcher.group(1).replaceAll("\"","").split(",");
assertThat(categories.length, is(2));
assertThat(categories[0], is("Jebb"));
assertThat(categories[1], is("Bush"));
There are many ways. One sloppy way to do it is /([A-Z])\w+/g
Please try it on your console like
var data = '{"device_types":["smartphone"],"isps":["a","B"],"network_types":[],"countries":[],"category":["Jebb","Bush"],"carriers":[],"exclude_carriers":[]}',
res = [];
data.match(/([A-Z])\w+/g); // ["Jebb", "Bush"]
OK the above was pretty sloppy however a solid single regex solution to extract every single element regardless of the number, one by one and to place them in an array (res) is the following...
var rex = /[",]+(\w*)(?=[",\w]*"],"carriers)/g,
str = '{"device_types":["smartphone"],"isps":["a","B"],"network_types":[],"countries":[],"category":["Jebb","Bush","Donald","Trump"],"carriers":[],"exclude_carriers":[]}',
arr = [],
res = [];
while ((arr = rex.exec(str)) !== null) {
res.push(arr[1]); // <- ["Jebb", "Bush", "Donald", "Trump"]
}
Check it out # http://regexr.com/3d4ee
OK lets do it. I have come up with a devilish idea. If JS had look-behinds this could have been done simply by reversing the applied logic in the previous example where i had used a look-forward. Alas, there aren't... So i decided to turn the world the other way around. Check this out.
String.prototype.reverse = function(){
return this.split("").reverse().join("");
};
var rex = /[",]+(\w*)(?=[",\w]*"\[:"yrogetac)/g,
str = '{"device_types":["smartphone"],"isps":["a","B"],"network_types":[],"countries":[],"category":["Jebb","Bush","Donald","Trump"],"carriers":[],"exclude_carriers":[]}',
rev = str.reverse();
arr = [],
res = [];
while ((arr = rex.exec(rev)) !== null) {
res.push(arr[1].reverse()); // <- ["Trump", "Donald", "Bush", "Jebb"]
}
res.reverse(); // <- ["Jebb", "Bush", "Donald", "Trump"]
Just use your console to confirm.
In c++ you can do it like this
bool foundmatch = false;
try {
std::regex re("\"([a-zA-Z]+)\"*.:*.\\[[^\\]\r\n]+\\]");
foundmatch = std::regex_search(subject, re);
} catch (std::regex_error& e) {
// Syntax error in the regular expression
}
If the number of items in the array is limited (and manageable), you could define it with a finite number of optional items. Like this one with a maximum of 5 items:
"category":\["([^"]*)"(?:,"([^"]*)"(?:,"([^"]*)"(?:,"([^"]*)"(?:,"([^"]*)")?)?)?)?
regex101 example here.
Regards.

Node-red SQL output object / Array conversion

I'm doing a SQL query in Node-Red to output a load of time/value data. This data is then passed to a web page for display in a graph.
Previously I've used php to do the SQL query, which I'm trying to replace. However SQL queries in php are delivered in a different format.
With Node-Red, I get:
[
{
"Watts": 1018,
"Time": 1453825454
},
{
"Watts": 1018,
"Time": 1453825448
},
{
"Watts": 1010,
"Time": 1453825442
}]
With PHP, I get:
[
[1453819620000,962],
[1453819614000,950],
[1453819608000,967],
[1453819602000,947]
]
I think I'm getting an array from php and an array of JSON objects from Node-Red. How do I convert the Node-Red object to be output from Node-Red in the same format as the PHP is? (Ie: I want to handle the processing at the server, rather than the client.)
A function node can be used to generate something in the same format.
var array = msg.payload;
var phpFormat = "[";
for (var i=0; i<array.length; i++) {
phpFormat += "[" +
// time format differ, NodeJS is in seconds
// php is in milliseconds
(array[i].Time * 1000 ) +
"," +
array[i].Watts + "],";
}
//take the last "," off
phpFormat = phpFormat.substring(0,phpFormat.lenght - 1);
phpFormat += "]";
msg.payload = phpFormat;
return msg;
I've had a bit of help from a chap at work and here is what he's come up with, modified for node-red by me:
var outputArray = [];
for(var i in msg.payload){
var entryData = [msg.payload[i]['Time']];
for(var attr in msg.payload[i]) {
if(attr!='Time') {
entryData.push(msg.payload[i][attr])}
};
outputArray.push(entryData); }
var returnMsg={"payload":outputArray};
return returnMsg;
I know, I know, this question is over 2 years old... however, for the next 500 people seeking an answer to a similar problem, I'd like to highlight the new JSONata expression feature built-in to the change node. Using this simple expression:
payload.[Time, Watts]
transforms your JS objects into the requested output of an array of arrays. In fact, much of my old repetitive looping through arrays has been replaced with some simpler (to me) expressions like this.
The magic of the lambda syntax evaluator is documented on the JSONata site. There you will also find the online exerciser where you can build an expression against your own data and immediately see the resulting structure.
Note: in order to use a jsonata expression in your change node, be sure to select the J: pulldown next to the input field (not the {} JSON option)... two totally different things!

turning a JSON object inside out

I'm trying to turn this JSON output inside-out. i.e. for some reason it's provided as rows-within-columns. I need it as the more conventional columns-within-rows.
This is closely related to, but not the same as, this question:
using Angular ng-repeat to display JSON rows/columns
But a new required feature is sorting on columns (using angular-tablesort), so I can't just fake up the table from the JSON output (as per the other question); the sort module chokes.
I've got to actually modify the incoming data, so it's there for the sorting algorithm. The trick to modifying it is that not all the data is in nice arrays (notice date only appesars once in the raw, but each time in the adjusted).
This is what I'm starting with:
$scope.rawJSON = {
'date':'2013-04-16',
'uid':[1,2,3],
'foo':['a','b','c'],
};
and this is how I want it to end up:
$scope.adjustedJSON = [
{date:'2013-04-16', 'uid':1,'foo':'a'},
{date:'2013-04-16', 'uid':2,'foo':'b'},
{date:'2013-04-16', 'uid':3,'foo':'c'},
];
Here:
var len = $scope.rawJSON.uid.length;
$scope.adjustedJSON = [];
for(var i = 0 ; i < len ; i++)
{
$scope.adjustedJSON.push({
date: $scope.rawJSON.date,
uid: $scope.rawJSON.uid[i],
foo: $scope.rawJSON.foo[i]
});
}