javascript, remove double quotes inside multiple array - json

I am trying to build a custom visual for datastudio, I got it working but there is a step, i can't fix, Datastudio generate a json file like this
export const message = {
"tables": {
"DEFAULT": [
{
"coordinateid": [
"143.4999336,-34.777302"
],
"colorid": [
"169,255,169"
],
"sizeid": [
1
]
},
{
"coordinateid": [
"143.4999358,-34.7773749"
],
"colorid": [
"169,169,169"
],
"sizeid": [
1
]
},
{
in deckgl the relevant code is
const drawViz = (data) => {
var data1 = data.tables.DEFAULT;
getPosition: d => d.coordinateid,
the only way to make it work, is when i remove the quotes from the values inside the array
"coordinateid": [
143.4999336,-34.777302
]
is there a way either to remove the double quotes between the bracket or a way just to parse the values and ignoring the double quotes

DataStudio returns GEO LatLong coordinates as a comma separated string. The correct way to parse this would be the following:
var baseCoordinate = "143.4999336,-34.777302";
// Split out the coordinates into multiple strings
var coordinates = baseCoordinate.split(",");
// Turn the strings into floats
var coordinatesAsNumbers = coordinates.map((coord) => parseFloat(coord));
This will give you the coordinates as floats in an array, which seems to be the format that deckgl is expecting.

find the answer
basically, change the javascript object to string using JSON.stringify the using regex to replace the strings then use Json.parese to change it back to an object
var data1 = data.tables.DEFAULT;
var data2 = JSON.stringify(data1);
var data3 = data2.replace(/\"]/g, "]");
var data4 = data3.replace(/\["/g, "[");
var data4 = JSON.parse(data4);

Related

Parsing JSON error cannot read property 'url' of undefined

I have been trying to parse JSON, which have 3 different set of data where one element have various number of children and sometimes none. I am getting an error when there is no children present or only one present. I declared the JSON as var data.
JSON A
{
"floorplan": [
{
"title": "plan1",
"url": "https://media.plan1.pdf"
},
{
"title": "plan2",
"url": "https://media.plan2.pdf"
}
]
}
JSON B
{"floorplan": []}
JSON C
{
"floorplan": [
{
"title": "plan1",
"url": "https://media.plan1.pdf"
}
]
}
I parsed the JSON like this:
var items = JSON.parse(data);
return {
floorplan1: items.floorplan[0].url;
floorplan2: items.floorplan[1].url;
}
But, it only returned data for the JSON A, for other 2 it gave TypeError: Cannot read property 'url' of undefined.
I modified the code to check if floorplan have at least one child and then parse data.
var items = JSON.parse(data);
var plan = items.floorplan[0];
if(plan){
return {
floorplan1: items.floorplan[0].url;
floorplan2: items.floorplan[1].url;
}
}
The new code returned data for JSON A and B(as empty row), but gave error for C. C have one child still it got the error.
I also tried this code, still got the error for JSON C.
var items = JSON.parse(data);
var plan = items.floorplan[0];
var plan1;
var plan2;
if(plan){
plan1 = items.floorplan[0].url;
plan2 = items.floorplan[1].url;
}
return{
floorplan1 : plan1 ? plan1 : null;
floorplan2 : plan2 ? plan2 : null;
}
Is there any method I can try to get data returned for all 3 types of JSON?
let data = `
[{"floorplan": [{
"title": "plan1",
"url": "https://media.plan1.pdf"
}, {
"title": "plan2",
"url": "https://media.plan2.pdf"
}]},
{"floorplan": []},
{"floorplan": [{
"title": "plan1",
"url": "https://media.plan1.pdf"
}]}]`;
let json = JSON.parse(data);
//console.log(json);
json.forEach(items=>{
//console.log(items);
let o = {
floorplan1: items.floorplan.length > 0 ? items.floorplan[0].url : '',
floorplan2: items.floorplan.length > 1 ? items.floorplan[1].url : ''
};
console.log(o);
o = {
floorplan1: (items.floorplan[0] || {'url':''}).url,
floorplan2: (items.floorplan[1] || {'url':''}).url
};
console.log(o);
o = {
floorplan1: items.floorplan[0]?.url,
floorplan2: items.floorplan[1]?.url
};
console.log(o);
const {floorplan: [one = {url:''}, two = {url:''}]} = items;
o = {
floorplan1: one.url,
floorplan2: two.url
};
console.log(o);
});
Sure. A few ways, and more than I have here. I have put all the raw data into one string, parsed it into json and then iterated through that. In each loop my variable items will correspond to one of the json variables you created and referenced in your question as items.
In the first example, I check to make sure that items.floorplan has at least enough elements to contain the url I'm trying to reference, then use the ternary operator ? to output that URL if it exists or an empty string if it doesn't.
In the second example, I use the || (OR) operator to return the first object that evaluates to true. If items.floorplan[x] exists, then it will be that node, and if it doesn't I provide a default object with an empty url property on the right hand side, and then just use the url from the resulting object.
In the third, I use the optional chaining operator that was introduced in 2020. This method will return undefined if the url doesn't exist.
In the fourth example, I use destructuring to pull values out of the items variable, and make sure that there is a default value for url in case the items variable doesn't have a corresponding value.
But there are many more ways to go about it. These are just a few, and you can't necessarily say which approach is better. It's dependent on your intent and environment. With the exception of optional chaining (which shows undefined if the property doesn't exist), you can see these produce the same results.
DOCS for optional chaining: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining
DOCS for destructuring: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment
An article on destructuring: https://javascript.info/destructuring-assignment

Find Text in a Named Range

I'm trying to get the row or index number of a string That is put in by the user. I retrieve the data in an array using spreadsheet.getRangeByName("Symbols").getValues(). The problem is it doesn't retrieve the data as strings it retrieves it as an array. So the result is an array of arrays. I wanted to use the function indexOf(result.getResponseText().toUpperCase()), but that doesn't work. Here is my code:
var aSymbols = spreadsheet.getRangeByName("Symbols").getValues();
Logger.log(aSymbols);
var row = aSymbols.indexOf(result.getResponseText().toUpperCase());
Logger.log(row);
And the results are:
[[ ], [XOM], [PLTR], [IBM], [VWAGY], [LIT], [ ], []]
I tried adding "[" and "]" to the search string, but that didn't work. I also tried using spreadsheet.getRangeByName("Symbols").getValues().toString(), but it returned 1 big long string. What am I missing?
Solution:
You can use findIndex() to get the index in 2D array:
var aSymbols = spreadsheet.getRangeByName("Symbols").getValues();
Logger.log(aSymbols);
var row = aSymbols.findIndex(function check(e) {return e[0] === result.getResponseText().toUpperCase()});
Logger.log(row);
Reference:
findIndex()
You could try this:
let aSymbolsArray = aSymbols.flat();
This will convert the double Array into a Array of strings.
function test(){
let aSymbols = [['' ], ['XOM'], ['PLTR'], ['IBM'], ['VWAGY'], ['LIT'], ['' ], ['']];
console.log(aSymbols);
//
// [ 'XOM' ],
// [ 'PLTR' ],
// [ 'IBM' ],
// [ 'VWAGY' ],
// [ 'LIT' ],
// [ '' ],
// [ '' ] ]
//
let aSymbolsArray = aSymbols.flat();
console.log(aSymbolsArray);
//
// [ '', 'XOM', 'PLTR', 'IBM', 'VWAGY', 'LIT', '', '' ]
//
}

How to extract JSON value in strangely formatted array?

I'm using a custom script for importing JSON into Google Sheets through a function. I can import values from propertys without any problem, but I have some problem with a specific array. It is a property which contains more information, but it seems the formatting makes the array into one single value instead of several (something with the slashes?). First, the script:
function getStat(url, propertyName)
{
let content = UrlFetchApp.fetch(url).getContentText();
let parsed = JSON.parse(content);
let processed = parsed.data
.filter(e =>
// Conditions go here:
e.season_format === 'Domestic League' &&
e.season === '2020/2021'
)
.map(e => e.stats[propertyName]);
return processed;
}
I want to get the value after "3" in the array called additional_info (simplified version below). But when I try to get the value, instead I get the third character in the array. I don't get "55" which is the value. I've tried with a bunch of variants. But I can't get it to work. For example, additional_info["3"] returns the third character in the array, not the value. Any tips? I've no problem getting the values of suspended_matches and home_AttackAdvantage.
{
"success": true,
"data": [
{
"season": "2020/2021",
"season_format": "Domestic League",
"stats": {
"suspended_matches": 20,
"homeAttackAdvantage": 3,
"additional_info": "{\"1\":1,\"2\":2,\"3\":55,\"4\"}"
}
}
]
}
The issue was that additional_info is yet another JSON string, so you have to parse it again.
function getStat(url, propertyName, additionalProp)
{
let content = UrlFetchApp.fetch(url).getContentText();
let parsed = JSON.parse(content);
let processed = parsed.data
.filter(e =>
// Conditions go here:
e.season_format === 'Domestic League' &&
e.season === '2020/2021'
)
.map(e => additionalProp
? [
e.stats[propertyName],
JSON.parse(e.stats.additional_info)[additionalProp]
]
: e.stats[propertyName]
);
return processed;
}
This gives you a function you can use in a formula:
=getStat(
"https://api.footystats.org/team?key=example&team_id=93",
"suspended_matches",
"330"
)
If you don't specify the third argument, it will just return a single column.

Restructuring a large amount of values in a JSON file

I have a JSON file with a large amount of the following values:
"values": [
"Foo": 1,
"Bar": 2,
"Baz": 3,
...
],
How do I efficiently convert this into:
"values": [
{
"name": "Foo",
"value": 1
},
{
"name": "Bar",
"value": 2
},
{
"name": "Baz",
"value": 3
},
...
],
Any help would be appreciated!
Okay, so there are two problems with your input. The first is the fact that the given JSON is invalid, so can't directly be parsed. The square brackets after "values" should be curly brackets, to allow for a hash instead of an array:
let raw_old_data =
// Read the old file
fs.readFileSync('./input_data.json').toString()
// Remove all newlines which could interfere with the regex
.replace(/[\r\n]/g, '')
// Replace the square brackets after `"values"` with curly braces
.replace(/"values": \[(.+?)\]/g, '"values": { $1 }');
To convert this (now valid) string to a JSON object, you use JSON.parse:
let old_data = JSON.parse(raw_old_data);
The second problem is that the format in which the values are stored doesn't match your needs. You want to convert from { key: "value" } to [ name: "key", value: "value" ]. The following function can do that, assuming your version of Node supports ES6 (If not, look at Murillo's answer):
function fix_format(obj) {
// This is where we keep the new items in the correct format
let res = [];
// Loop over all values
Object.keys(obj.values).forEach(name => {
let value = obj.values[name];
// Change the format and add to resulting array
res.push({
// If the variable is the same as the key of the hash, it doesn't have to be specified
name,
value,
});
});
return res;
}
All that's then left to do is loop all data from the old object through that function with the Array.map function:
let new_data = old_data.map(fix_format);
And optionally write it back to a file to use with a different program:
fs.writeFileSync('./formatted_data.json', JSON.stringify(data, null, 2));
Note: The 2 in the JSON.stringify function indicates that the resulting JSON should be padded with 2 spaces, to keep it readable.
With ES6:
Object.keys(values).map(name => ({
name,
value: values[name]
}))
Without ES6:
var keys = Object.keys(values);
var newValues = [];
for(var i = 0; i < keys.length; i++){
newValues.push({
name: keys[i],
value: values[keys[i]]
})
}
If your intention is to use the received data i.e obtain data from DB (e.g MSSql, MySql...) using the connection.query(your_custom_sql_query, (err, rows, fields)
for more info:Node.js MySQL Select From Table
I'll recommend you to use:
const myJson = JSON.stringify(rows[0]);

How can i list the values of a Node in JSON ?

Say, I have a JSON that has an array of "Topics"
I need to list all "created_at" values of all the topics
without the other data , using the Chrome console
P.S : I'm Using JSONView
You can loop through the objects in your array and simply access the property created_at.
Example
var json = {
all_topics: [{
"created_at:" "2016-08-08T10:22:03.123Z",
"name": "topic1"
}, {
"created_at": "2016-08-08T11:43:06.963Z",
"name": "topic2"
}]
}
for (var topic of json.all_topics) {
console.log(topic.created_at);
}
You can use JSON.stringify to turn a JavaScript object into a JSON String, and JSON.parse to turn a JSON string into a JavaScript object.
var jsonString = JSON.stringify(json);
==> {"all_topics":[{"created_at":"2016-08-08T10:22:03.123Z","name":"topic1"},{"created_at":"2016-08-08T11:43:06.963Z","name":"topic2"}]}
var jsonObj = JSON.parse(jsonString);
==> Object {all_topics: Array[2]}
Alternatively, you could return a new array with the filtered property using Array.prototype.map:
var topics = json.all_topics.map(function(obj){
return obj.created_at;
});
==> ["2016-08-08T10:22:03.123Z", "2016-08-08T11:43:06.963Z"]