I am attempting to use Apps Script to convert the values in a sheet to a multi-level JSON.
It is easy enough to convert the values to a single level JSON like this:
[{
"name": "Bob Jones",
"phone": "555-555-5555",
"street": "123 Somewhere St.",
"city": "Nowhere",
"state": "ID",
"postal": 45632,
"country": "USA"
}]
But, what I want, is this:
[{
"name": "Bob Jones",
"phone": "555-555-5555",
"address": {
"street": "123 Somewhere St.",
"city": "Nowhere",
"state": "ID",
"postal": 45632,
"country": "USA"
}
}]
Here is the code used to format the JSON:
function makeJSON_(object, options) {
if (options.format == FORMAT_PRETTY) {
var jsonString = JSON.stringify(object, null, 4);
} else if (options.format == FORMAT_MULTILINE) {
var jsonString = Utilities.jsonStringify(object);
jsonString = jsonString.replace(/},/gi, '},\n');
jsonString = prettyJSON.replace(/":\[{"/gi, '":\n[{"');
jsonString = prettyJSON.replace(/}\],/gi, '}],\n');
} else {
var jsonString = Utilities.jsonStringify(object);
}
return jsonString;
}
It would be easy enough to setup a "pre-conversion" sheet to create the JSON substring, but that isn't flexible and would be a beast to maintain.
How do I JSON.stringify() the sheet data to automatically create the substrings?
To go from the version of json you have to the one you want to go to you can do the following --
var json = [{
"name": "Bob Jones",
"phone": "555-555-5555",
"street": "123 Somewhere St.",
"city": "Nowhere",
"state": "ID",
"postal": 45632,
"country": "USA"
}]
for (var i=0; i < json.length; i++){
var currentObj = json[i];
// make a temporary address object
var address = {};
// copy all the attributes over to the temp object
address.street = currentObj.street;
address.city = currentObj.city;
address.state = currentObj.state;
address.postal = currentObj.postal;
address.country = currentObj.country;
// add address to the original object
currentObj.address = address;
// get rid of the following attributes from parent
delete currentObj.street;
delete currentObj.city;
delete currentObj.state;
delete currentObj.postal;
delete currentObj.country;
}
console.log(json);
Much easier than replacing things in a string.
http://codepen.io/anon/pen/XKOrXa
Related
How can I get the 'address' array within of request response object below?
{
"title": "MRS.",
"name": "Aluno",
"lastName": "3",
"birthday": "2019-08-31",
"address": [
{
"addressName": "rua 2",
"zipCode": "13901264",
"city": "amparo",
"state": "sp",
"country": "brasil"
},
{
"addressName": "rua 2",
"zipCode": "13901264",
"city": "amparo",
"state": "sp",
"country": "brasil"
},
]
}
If I save this object in a state called customer and print console.log(customer.address) it works well and I can see the address informations, but I can't use map or forEach methods like customer.address.forEach, I receive an error :(
You can use methods such as map, reduce, filter, forEach only on Array Not on Object.
the key address has value as an object, To read it you can simply use
console.log(customer.address.addressName) //street x
console.log(customer.address.zipCode) //13901264
If you want to loop through properties
Object.values(customer.address).forEach((value) => {
console.log(value);
})
// OR
Object.keys(customer.address).forEach((key) => {
console.log(customer.address[key]);
})
The property address it not an array, if you need to convert it into an array of one element you can use:
const valueAsArray = [response.address]
Object.keys(out.address).map(key => {
console.log(out.address[key]);
// etc ...
})
I have over 1000s of dictionaries in JSON after an API request. How do create a script that iterates over all dictionaries and stores the values of one of the key-value pairs?
example
},"testData"
{
"testJSON": "test",
"phone": null,
"address: "122 main st"
}, "testData1"
{
"testJSON": "test1",
"phone": null,
"address: "123 main st"
},
For example, how do I get the "address" field of every single JSON dictionary?
You need to first parse your json, like this:
var json = JSON.parse(jsonString);
then you could iterate your json keys and do something with the root values, like such:
for(var el in json)
{
console.log(json[el]) // will log every root element
console.log(json[el].phone) // will log phone of each element
}
example fiddle: https://jsfiddle.net/1ky6dzen/
In python this can be done like this:
data = [{
"testJSON": "test",
"phone": null,
"address: "122 main st"
}, "testData1"
{
"testJSON": "test1",
"phone": null,
"address: "123 main st"
}]
my_array = []
for obj in data:
my_array.append(obj['address'])
print(my_array)
Hope this is what you were after :)
Use forEach loop to iterate over the keys of the object
var a={"testData":
{
"testJSON": "test",
"phone": null,
"address": "122 main st"
}, "testData1":
{
"testJSON": "test1",
"phone": null,
"address": "123 main st"
}};
Object.keys(a).forEach(e=>console.log(a[e].address))
I have this normal array
["Company="Google",Country="USA",Id="123"", "Company="Volvo",Country="SWEDEN",Id="999""]
And I would like to build an object out of its values.
Expected result is
{
"root": [{
"Company": "Google",
"Country": "USA",
"Id": "123"
}, {
"Company": "Volvo",
"Country": "SWEDEN",
"Id": "999"
}
]
}
How do I work this structure in JavaScript?
the array you posted is not valid we'll need to mix single and double quotes like this:
['Company="Google",Country="USA",Id="123"', 'Company="Volvo",Country="SWEDEN",Id="999"']
if you're getting the array as a response from a request and you copied it from console than it quotes must've been escaped using \" and you don't have to fix it.
converting the array into an object:
var myArray = ['Company="Google",Country="USA",Id="123"', 'Company="Volvo",Country="SWEDEN",Id="999"']
var myObject = array2obj(myArray);
function array2obj(myArr) {
var myObj = {root:[]}
myArr.forEach(function(v) {
var currentObj = {}
v.split(",").forEach(function(vi) {
var tmp = vi.replace(/\"/g, "").split("=");
currentObj[tmp[0]] = tmp[1];
});
myObj.root.push(currentObj);
});
return myObj
}
as you can see you call the function like this var myObject = array2obj(myArray) assuming your array is stored in myArray.
now you have your object in the variable myObject:
{
"root": [
{
"Company": "Google",
"Country": "USA",
"Id": "123"
},
{
"Company": "Volvo",
"Country": "SWEDEN",
"Id": "999"
}
]
}
"reducing" the array into ids only:
as asked in comments, the following will produce a newArray = ["123", "999"]
var myArray = ['Company="Google",Country="USA",Id="123"', 'Company="Volvo",Country="SWEDEN",Id="999"'];
var newArray = myArray.map(function(x) {
var id = /,\s*id\s*=\s*"(.*?)"/gi.exec(x);
if (id) return id[1]
});
I'm using regex to match the id and .map() to create a new array with the matched results.
if you want the array to contain numbers and not strings replace return id[1] with return Number(id[1]) but you have to make sure ids are always numbers or you will get NaN errors
I am attempting to create a Google map with data from two separate json files. I'm trying to use jquery/javascript to combine the two files and then process the resulting array of objects through the Google Maps API.
I've tried $.extend, $.merge, concat, and I've even tried pushing the data into an empty array, but in each case only the first set of data is appearing on the map (although I can see both sets of data separately if I display them with console.log).
I must be doing something fundamentally wrong, but I'm not seeing it. The relevant part of my code is as follows (with the things I've tried commented out). Any suggestions would be most appreciated.
j$.when(
j$.getJSON('mapData1.js'),
j$.getJSON('mapData2.js')
).done(function(data1, data2) {
var d1 = data1;
var d2 = data2;
var d3 = [];
d3.push(d1[0]);
d3.push(d2[0]);
//var d3 = j$.extend({},d1,d2);
//var d3 = j$.merge(d1,d2);
//var d3 = d1.concat(d2);
var data = d3[0];
//code to process data with Google Maps API
});
My json files look like this (but with many more items):
[
{
"ID": "a001a000002o4iZAAQ",
"NAME": "Atlanta",
"Address": "123 State Street",
"City": "Atlanta",
"StateAbbreviation": "GA",
"SF": "",
"LeaseExpiration": "8/31/2012",
"Occupancy": "2",
"Country": "USA",
"Address2": "",
"Lat": "33.7863317",
"Lng": "-84.3836873",
"Type": "loc",
"Color": "red"
}
]
you can use concat()
var array1 = [{
"ID-1": "a001a000002o4iZAAQ",
"NAME-1": "Atlanta",
"Address-1": "123 State Street",
"City-1": "Atlanta",
"StateAbbreviation-1": "GA",
"SF-1": "",
"LeaseExpiration-1": "8/31/2012",
"Occupancy-1": "2",
"Country-1": "USA",
"Address2-1": "",
"Lat-1": "33.7863317",
"Lng-1": "-84.3836873",
"Type-1": "loc",
"Color-1": "red"
}];
var array2 = [{
"ID-2": "a001a000002o4iZAAQ",
"NAME-2": "Atlanta",
"Address-2": "123 State Street",
"City-2": "Atlanta",
"StateAbbreviation-2": "GA",
"SF-2": "",
"LeaseExpiration-2": "8/31/2012",
"Occupancy-2": "2",
"Country-2": "USA",
"Address2-2": "",
"Lat-2": "33.7863317",
"Lng-2": "-84.3836873",
"Type-2": "loc",
"Color-2": "red"
}];
var array3 = array1.concat(array2);
alert(JSON.stringify(array3));
Let's say I start with this:
var shippingAddresses = [
{
"firstname": "Kevin",
"lastname": "Borders",
"address1": "2201 N Pershing Dr",
"address2": "Apt 417",
"city": "Arlington",
"state": "VA",
"zip": "22201",
"country": "US"
},
{
"firstname": "Dan",
"lastname": "Hess",
"address1": "304 Riversedge Dr",
"address2": "",
"city": "Saline",
"state": "MI",
"zip": "48176",
"country": "US"
}
]
I use this to prepopulate a form.
Users can edit entries or add new ones. I need to prevent them from adding duplicates.
The issue is that the structure of the form that I am serializing and the order these values are returned from the database are not the same, so there is a chance that I will insert an item into this array with the following format:
{
"country": "US",
"firstname": "Kevin",
"lastname": "Borders",
"address1": "2201 N Pershing Dr",
"address2": "Apt 417",
"zip": "22201",
"city": "Arlington",
"state": "VA"
}
Which is the same as the first entry, just ordered differently.
I am loading underscorejs, so if there's a way to handle it with that library that would be great. I'm also using jQuery if that helps.
At this point I'm not sure how to proceed.
The Underscore findWhere function does exactly what you need - it's not an indexOf search by object identity, but searches objects whose properties have the same values as the input.
if (_.findWhere(shippingAddresses, toBeInserted) == null) {
shippingAddresses.push(toBeInserted);
}
Basic example using lodash union method:
var a = [1,2,3];
// try to add "1" and "4" to the above Array
a = _.union(a, [1, 4]);
console.log(a);
<script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/4.13.1/lodash.min.js"></script>
While this doesn't directly answers the question, it does answers the broader question of how to add unique values to an Array, and like myself, others might stumble upon this page from google.
based on this answer to: "js-remove-an-array-element-by-index-in-javascript"
https://stackoverflow.com/a/7142909/886092
I'm using the following idiom that is concise and does not require underscore.js or any other framework.
Here is an example for recording selected and deselected rows for DataTables jquery plugin.
I keep an array of currently selected ids, and I don't want to end up with duplicates in the array:
in coffeescript
fnRowSelected: (nodes) ->
position = $selected.indexOf(nodes[0].id)
unless ~position
$selected.push nodes[0].id
return
fnRowDeselected: (nodes) ->
position = $selected.indexOf(nodes[0].id)
if ~position
$selected.splice(position, 1)
More generally it would
position = myArray.indexOf(myval)
unless ~position
myArray.push myVal
or in JS
var position;
position = myArray.indexOf(myval);
if (!~position) {
myArray.push(myVal);
}
If you want to check the user input object you could try this function:
var uniqueInput = {
"country": "UK",
"firstname": "Calvin",
"lastname": "Borders",
"address1": "2201 N Pershing Dr",
"address2": "Apt 417",
"city": "Arlington",
"state": "VA",
"zip": "22201"
};
var duplicatedInput = {
"country": "US",
"firstname": "Kevin",
"lastname": "Borders",
"address1": "2201 N Pershing Dr",
"address2": "Apt 417",
"city": "Arlington",
"state": "VA",
"zip": "22201"
};
var shippingAddresses = [{
"firstname": "Kevin",
"lastname": "Borders",
"address1": "2201 N Pershing Dr",
"address2": "Apt 417",
"city": "Arlington",
"state": "VA",
"zip": "22201",
"country": "US"
}, {
"firstname": "Dan",
"lastname": "Hess",
"address1": "304 Riversedge Dr",
"address2": "",
"city": "Saline",
"state": "MI",
"zip": "48176",
"country": "US"
}];
function checkDuplication(checkTarget,source){
_.each(source,function(obj){
if(_.isEqual(checkTarget,obj)){
alert("duplicated");
}
});
}
And try to invoke this check function in different parameter (uniqueInput and duplicatedInput)
I think it could check the duplication input in your shipping addresses.
checkDuplication(uniqueInput,shippingAddresses);
checkDuplication(duplicatedInput,shippingAddresses);
I make a jsfiddle. You could try it.
Hope this is helpful for you.
EDIT, this will work with your example of unsorted properties:
var normalized_array = _.map(shippingAddresses, function(a){
var o = {};
_.each(Object.keys(shippingAddresses[0]), function(x){o[x] = a[x]});
return o;
})
var stringy_array = _.map(normalized_array, JSON.stringify);
shippingAddresses = _.map(_.uniq(stringy_array), JSON.parse});
and we could do this with a one-liner but it would be super ugly:
shippingAddresses_uniq = _.map(_.uniq(_.map(_.map(shippingAddresses, function(a){ var o = {}; _.each(Object.keys(shippingAddresses[0]), function(x){o[x] = a[x]}); return o; }), JSON.stringify)), JSON.parse});
I think you need this,
NOTE: No library is required.
let array = [{ id: 1}, {id: 2}, {id: 3}];
function addUniqeObj(data) {
let index = -1;
for(let i = 0, i < array.length; i++) {
if(array[i].id === data.id) {
index = i;
}
}
if(index > -1) {
array[index] = data;
} else {
array.push(data)
}
}
Basic example using Set() from ECMAScript 2015 (no library required)
The Set object lets you store unique values of any type (whether primitive values or object references). If an iterable object is passed, all of its elements will be added to the new Set. Here I'll just add one value:
// original array with duplicates already present
const numbers = [1, 1, 1, 2, 3, 100]
// Use Set to remove duplicate elements from the array
// and keep your new addition from causing a duplicate.
// New value (100) is not added since it exists (and array
// also is de-duped)
console.log(Array.from(new Set([...numbers, 100])))
// [1, 2, 3, 100]
// New, non-existing value (101) is added (and array is de-duped)
console.log(Array.from(new Set([...numbers, 101])))
// [1, 2, 3, 100, 101]