Combine strings and arrays into JSON properly - javascript

I've fetched some data from XML document and assigned them into three variables. Root element name, array which contains all the names of root's children and second array with length of those children sub-nodes. I want to convert those variables into the JSON object in this way:
{ "root_name": {
"childName[0]": "lengthSubNodes[0]",
"childName[1]": "lengthSubNodes[1]",
"childName[2]": "lengthSubNodes[2]",
}
with this function:
function XMLtoJSON(rootName,childNames,childNumbers){
var xmlObject = {}
xmlObject[rootName] = {};
for(var i = 0; i < childNames.length; i++ ){
xmlObject[rootName][childNames[i]] = childNumbers[i];
}
}
Everything works fine. However when it comes to XML document with many root's children with the same name and length they appear just once like this:
{ "catalog": {
"book": 6
}
and should look like this:
{ "catalog": {
"book":6,
"book":6,
"book":6
}
Do you know how to fix it?

You cannot have multiple keys of the same name under one parent. Also, nodes in xml have an order, which is lost under a js map. So if you want a xml to json utility, you need to create yourself a json schema. Here is a simplistic example:
{
name: "catalog",
value: null,
children: [
{
name: "book",
value: 6
},
{
name: "book",
value: 6
},
{
name: "book",
value: 6
},
]
}

Related

Return true if an array within an array contains specific key

I have the following the object:
items: [
{
object_a {
id: "1",
value: "somevalue1"
}
},
{
object_b {
id: "2"
value: "somevalue2"
items:[
{
nested_object_a {
id: "3"
value: "somevalue3"
},
nested_object_b {
id: "4"
value: "somevalue4"
},
}
]
}
},
]
I can check if the value key exists in the initial items array:
items.some(item => item.hasOwnProperty("value"));
To see if the value key exists in the nested object_b item array I can do the following:
items[1].object_b.items.some(item => item.hasOwnProperty("value"));
Instead of specifying which number in the array to look in I need to make the final expression dynamic. I'm certain I need to do a find or a filter on the top level items, but I've had no luck with it so far.
I found that using an every function on the items allowed me to return the boolean value I required form the array. The problem this created is any array item that didn't have the object_b key on was returning null and breaking my app. It turns out I needed to use an optional chaining operator to get around this (.?).
Thanks to #ikhvjs for linking that stackedoverflow article.
Working code:
items.every(item => {
item.object_b?.items.some(item => item.hasOwnProperty("value"));
});

Constructing nested array based on database data

I am using a template that renders a menu with a predefined structure. I have a database with some menus there and i am already retrieving them. The problem is that i need to somehow make the logic to construct the predefined structure with the menus i get from the database. Here it is an example of what i am trying to explain:
export const MainNav = [
{
icon: "pe-7s-rocket",
name: "Dashboards",
content: [
{
name: "Analytics",
url: "#/dashboards/analytics",
},
{
name: "Commerce",
content: [
{
name: "Blabla",
url: "#/dashboards/commerce",
},
{
name: "Sales",
url: "#/dashboards/sales",
},
]
},
],
{
name: "Minimal",
content: [
{
name: "Variation 1",
url: "#/dashboards/minimal-dashboard-1",
},
{
name: "Variation 2",
url: "#/dashboards/minimal-dashboard-2",
},
],
},
{
name: "CRM",
url: "#/dashboards/crm",
},
];
Basically it is an array of objects with nested arrays/objects.
I really need some guide, i think i need to use recursion but i don't know how. Basically a submenu will have to go inside the content property of their parent object.
Since the content key is always the one that potentially has children, check it's length and add a nested loop if it contains more than 1 child.
for (let i = 0; i < MainNav.length; i++) {
let parent = MainNav[i];
// create parent nav element here, accessing it's properties i.e. parent.name
if (parent.content) { //so you don't get reference errors
if (parent.content.length > 1) {
for (let v = 0; v < parent.content.length; v++) {
let nestedChild = parent.content[v];
// append child nav elements here
}
}
}
}

How to create a new object with parts of existing object that may have nested object

I need to mirror the structure of page items in an InDesign document in a javascript object. I need it to match the nesting of page items in groups, groups within groups, etc.
This needs to be extensive to work with any InDesign document that is being worked on.
I need a recursive function that will build my object adding the child frames of any groups it finds and groups within those child frames, etc.
calling the same function if I find a group.
I've tried functions that call themselves if they come across a group, but I get a stack error on large files, on smaller files I only get results that go two levels deep.
var doc = app.activeDocument;
var page = doc.pages[0];
var article = {
id: page.id,
frames: new Array()
}
for(i=0;i<page.pageItems.length;i++){
var po = page.pageItems[i];
var frame_objs = new Array();
var frame_obj = {id: page.pageItems[i].id};
if(po.getElements()[0].constructor.name == "Group"){
frame_obj.frames = getChildFrames(po.pageItems);
}
article.frames.push(frame_obj);
}
create_file("~/Desktop/", "article.json", article);
function getChildFrames(pi_children){
var child_frame_objs = new Array();
for(i=0;i<pi_children.length;i++){
var child_obj = {id: pi_children[i].id};
if(pi_children[i].constructor.name == "Group"){
child_obj.frames = getChildFrames(pi_children[i].pageItems);
}
child_frame_objs.push(child_obj);
}
return child_frame_objs;
}
The idea is to create a object something like this:
{
id: 1,
components: [
{
type: "TextFrame",
id: 201,
}
{
type: "Group",
id: 203,
childFrames: [
{
type: "Rectangle",
id: 1102
},
{
type: "Group",
id: 2034,
childFrames: [
{
type: "TextFrame",
id: 2345
},
{
type: "Group",
id: 99983,
childFrames: [
etc...
]
}
]
}
]
}
]
}
I expect to get a properly simplified version of the page frames structure. As deeply nested as the layout is.
Can someone help me understand how to do this?

How to create an array as such using javascript

Using javascript, I want to create an array that has the structure so that it can have all states within the country array. Each state would be an array consisting all the regions within it. And each region would contain all the health clubs within it. Something like this:
[Australia]=>array([NSW]=>array([Sydney]=>array(element1, element2, ...)));
So far I have tried many things including the code below:
$('#search-widget-data li').each(function(){
var dataElement = $(this);
searchWidgetData.push(dataElement.text());
alldata.push([dataElement.prevAll(".state:first").text(),
dataElement.prevAll(".region:first").text());
});
You can use a form like this:
var countries = [
{
name: "Australia",
states: [
{
name: "state1",
regions: [
{
name: "region1",
healthclubs: [
"healthclub1", "healthclub2"
]
},
{
name: "region2",
healthclubs: [
"healthclub1", "healthclub2"
]
}
]
},
{
name: "state2",
regions: [
{
name: "region1",
healthclubs: [
"healthclub1", "healthclub2"
]
}
]
}
]
},
{
name: "USA"
}
];
You may want to store your data structure in the JSON format which will make it easy for storage and working with as a JavaScript object.
You may try this one out.
var regArr[n1][n2];
but you need to specify the length of each inner array.

Creation of a multi-level JSON string

I want to create a multi-level JSON string with JS.
Scenario
3 countries with 5 grandfathers with 3 kids which whom also have 3 kids that have 5 friends.
I get the data from a external JSON file that looks like this.
{"countries":[
{
"name":"USA",
"grandfathers":[
{
"gFName":"Steve",
"grandfathersKid":[
{
"gFKName": "Linda",
"kid": [{
"name": "Steve JR",
"friends": [{
"name": "Kriss|John|Martin|Steven"
}]
}
]
}
]
}
]
}
]}
And now I want to store some of the countries with people and their relatives and friends in a a new JSON list that looks exactly as the list made in the external json file. I aim to use this "homemade" list later on in the script.
My initial response for this was
var tree = new Array();
tree = {};
var countries = new Array();
countries[0] = "canada";
countries[1] = "USA";
countries[2] = "Mexico";
countries[0][0] = "Steve"; //Lives in Canada
countries[0][0][0] = "Linda"; //Daughter of Steve
countries[0][0][0][0] = "Steve JR"; // Kid of Linda
countries[0][0][0][0][0] = "Kriss"; //Steves Friend
...
$.each(countries...function(index, value){
tree[index].country = value;
$.each(grandfathers...function(key, value){
tree[index].country[key].grandfather = value;
}
And so on, but this is not giving me the result I want. What am I doing wrong? And a more effective way than to take each of everything?
Third edit...
Is this the sort of thing you're trying to do?
var countries = $.map(oldCountries || [], function(country) {
return {
name: country.name,
people: $.map(country.grandfathers || [], function(gpa) {
return {
name: gpa.gFName,
children: $.map(gpa.grandfathersKid || [], function(parent) {
return {
name: parent.gFKName,
children: $.map(parent.kid || [], function(kid) {
return {
name: kid.name,
friends: kid.friends
};
})
};
})
};
})
};
});
I wasn't sure what to do with the friends node. Should that be normalized into something more useful, or do you want to leave it alone?
This Fiddle demonstrates the technique.
I think we'd need to know more about your requirements. But several thing I see here are:
You declare tree and initialize it as an Array, then immediately reinitialize it as an
empty object
You are not creating the intermediate nodes here, such as tree[index] but just assuming
that they exist.
You are trying to assign the country[key] property of an object, using the dot-property
access.
Can you supply the countries structure and the grandfather's structure. And are they nested?
And finally, what would you like for the output format? The code above hints at it, but it's still a little fuzzy.
Edit
So are you trying to achieve a structure something like this?:
var countries = [
{
name: "Canada",
people: [
{
name: "Steve",
children: [
{
name: "Linda",
children: [
{
name: "Steve, Jr.",
friends: [
{
name: "Kriss"
}
//, more friends
]
}
//, more grandchildren
]
}
//, more parents
]
}
//, more grandparents
]
}
//, more countries
];
May be this jsfiddle can help you to get started?
And here is an example derived from your code.
Sounds like a homework, so I'll try to point you in the right direction. I think you are confusing objects and arrays. You could use a "country" object and a "person" object. A country object should have an array of person objects, as inhabitants. Person objects can have an array of person objects as descendants. Add a method like "addDescendant", which creates a new person under a person. From There you can build the structure as you like. Here is some pseudo code:
countries = [];
function Country(name){ this.name = name; this.population = [];}
function Person(kids){this.descendants = []; this.addDescendant = function(){...};
//loop from 1 to kids and add descendants as "new Person"
}
person = new Person(3);
country1 = new Country("MyCountry1");
// now add people to country1.population
countries.push(country1);
The final structure should look something like this:
countries = [
{ name: "country 1",
people: [{ name: "Steve"},
{name: "Clara", descendants: [{name: "Clara's daughter"},
{name: "Clara's son"}]
]}
},
{ name: "country 2",
people: [{}, {} ...]
}
];

Categories

Resources