I need a recursive function in javascript, which can return me all fieldname (Key Name) of my json document store in MarkLogic. JSON document is very dynamic and have multiple hierarchical elements. So need a function which can traverse through JSON and fetch all fieldname (Keys Name).
One option I thought was to get entire document into MaP object and run Map function to get all keys. But not sure whether MarkLogic allows to capture entire json doucment into Map and one can read fields names.
Thanks in Advance
Got the function to iterate through JSON document to pull Key Name
Sample JSON
var object = {
aProperty: {
aSetting1: 1,
aSetting2: 2,
aSetting3: 3,
aSetting4: 4,
aSetting5: 5
},
bProperty: {
bSetting1: {
bPropertySubSetting : true
},
bSetting2: "bString"
},
cProperty: {
cSetting: "cString"
}
}
Solution available at StackOverflow
Recursively looping through an object to build a property list
*
function iterate(obj, stack) {
for (var property in obj) {
if (obj.hasOwnProperty(property)) {
if (typeof obj[property] == "object") {
iterate(obj[property], stack + '.' + property);
} else {
console.log(property + " " + obj[property]);
$('#output').append($("<div/>").text(stack + '.' + property))
}
}
}
}
iterate(object, '')*
This handy page may help: MarkLogic - Native JSON
The following will extract all property names
var json = fn.head(xdmp.unquote('{ foo : "bar", baz : { buz: "boo", chicken : { option1 : "soup", option2 : "salad" } } }'))
json.xpath("//*/name()");
Output: foo baz buz chicken option1 option2
If, after reviewing the samples on that page you still need assistance, I suggest updating your question with example JSON and desired output (even if it is meant to be dynamic, an example people can copy/paste and work with helps alot)
Related
This question already has answers here:
How can I access and process nested objects, arrays, or JSON?
(31 answers)
Closed 6 years ago.
I have a json like this :
{
"Project
[id=1, dateDebut=2017-01-13, dateFin=2017-01-18, description=qsd, sponsor=qsd ]"
:
[
{"id":1,"title":"qsd ","description":"qsdqsd","dateFin":"2017-01-26"},
{"id":2,"title":"sss ","description":"sss","dateFin":"2017-01-26"}
]
}
originated from : return new ObjectMapper.write(Map<Project,List<Task>> projectTasks = new LinkedMultiValueMap<>()) ;
EDIT : this is the real response :
{"Project [id=1, name=qsdsqd, type=null, done=false, dateDebut=2017-01-13, dateFin=2017-01-18, description=qsd, sponsor=qsd, client=qsd, showable=true]":
[{"id":1,"title":"qsd ","description":"qsdqsd","dateFin":"2017-01-26","dateDebut":"2017-01-14","period":null,"done":false,"status":"Actif","priority":"Normal"},
{"id":2,"title":"task 2 ","description":"qsdqsd","dateFin":"2017-01-26","dateDebut":"2017-01-14","period":null,"done":false,"status":"Actif","priority":"Normal"}]}
How can I read the list of tasks in the client side ?
First of all, your JSON is not valid. Are you sure that is a line break between the word Project and [id...]. A valid JSON would be:
{
"Project [id=1, dateDebut=2017-01-13, dateFin=2017-01-18, description=qsd, sponsor=qsd, ]":
[
{"id":1,"title":"qsd ","description":"qsdqsd","dateFin":"2017-01-26"},
{"id":2,"title":"sss ","description":"sss","dateFin":"2017-01-26"}
]
}
You can have object key names like that. But i'ts not very friendly to retrieve data.
If you cannot change your data schema (or just don't want), you can iterate over the Object with the
Object.keys(obj).forEach ( (key) => {
console.log('key: ' + key);
console.log('value: ' + obj[key]);
/* you can iterate over your value (tasks) here */
obj[key].forEach( (task) => {
console.log('task1: ', task);
});
}); //where obj is your json
Or you can access the first object property with:
obj[Object.keys(obj)[0]]; //where obj is your json
EDIT As pointed by #André Dion, forEachis best suited to iteration, not map. And we're assuming your response is already parsed from the server (by yourself or by a lib like jquery). If not, you should do a JSON.parse(response); to retrieve the object.
You may try this:
Assume above response in stored in var response.
for(var project in response) { // this will get every project
for(var i=0; i<project.length; i++) { // this will iterate over the array for each project which are your tasks.
console.log("task" + project[i]);
console.log(project[i]["id"]); // access each tasks id, similar for other attributes
}
}
This question already has answers here:
Accessing an object property with a dynamically-computed name
(19 answers)
Closed 7 years ago.
I have the following code which works fine:-
$.getJSON("shipping.json")
.done(function(data) {
getUniqueCountries = function() {
var countries = [];
$.each(data.Services.intl.en, function( i, item ) {
if (countries.length==0) {
countries += item.countries;
}
else
{
countries += "," + item.countries;
}
});
}
})
However, I would like to make the first part of the $.each dynamic as this could be one of 3 possibilities based on a predefined variable, e.g.
var foo = "intl"
so the new line would read:-
$.each(data.Services.foo.en, function( i, item )
I can add another line of code and use an eval which works fine, but understand that this is not seen as best practice. i.e.
var foo = "intl";
var bar = eval("data.Services." + foo + ".en");
$.each(bar, function( i, item )
I have tried using JSON.parse (as seems to be popular way to resolve on google) instead of eval, i.e.
var bar = JSON.parse("data.Services." + foo + ".en");
but get an error :
'Unexpected token d'.
A snippet of the JSON file if needed :-
{
"Services": {
"intl": {
"en": [
{
"service": "PREMIER",
"countries": "United Kingdom",
"date": "Thursday 24th 10:00"
}
]
}
}
}
So I would like to know how to pass the variable foo into JavaScript to get the correct data and not get an error, without using the Eval function, or am I good to use the Eval function after all?
Thanks in advance for any help
If i'm understanding correctly, you should be able to do the following:
$.each(data.Services[foo].en, function( i, item ) {
if (countries.length==0) {
countries += item.countries;
}
else
{
countries += "," + item.countries;
}
});
Properties in javascript objects can be accessed as if you are accessing a particular key inside an array. For example you can do window.location or window["location"]
Hope this helps
It's actually fairly simple. JavaScript supports dynamic object keys with the [] notation:
data.Services[foo].en // Where foo = 'intl' or something.
A javascript data object (JSON notation) has been created with the following content:
"[
{"range":"Shape","values":[{"idx":0,"val":"Random"},{"idx":1,"val":"Line"},{"idx":2,"val":"Square"},{"idx":3,"val":"Circle"},{"idx":4,"val":"Oval"},{"idx":5,"val":"Egg"}]},
{"range":"Color","values":[{"idx":0,"val":"Red"},{"idx":1,"val":"Blue"},{"idx":2,"val":"Yellow"},{"idx":3,"val":"Green"},{"idx":4,"val":"Cyan"}]}
]"
In a next step the index of an ordinal value has to be found in this object. The function should find the index of the value 'Blue' in the range 'Color'.
So the function should have the meta scripting form
f("Color")("Blue")=1
What is the most elegant form to create such a function in the context of D3 and javascript?
Depending on your use case, it might make sense to convert the data structure to a different structure more suitable for direct access. E.g. you could convert your structure to
var data = {
Shape: ['Random', 'Line', ...],
// ...
};
and access it with
data['Shape'].indexOf('Line') // or data.Shape.indexOf('Line')
Or go even one step further and convert to
var data = {
Shape: {
Random: 0,
Line: 1,
// ...
},
// ...
};
and access it with
data['Shape']['Line'] // or data.Shape.Line
What the best solution is depends on the actual use case.
Converting the structure dynamically is pretty straight forward. Here is an example to convert it to the first suggestion:
var newData = {};
data.forEach(function(item) {
newData[item.range] =
item.values.map(function(value) { return value.val; });
});
This would also reduce redundancy (e.g. idx seems to correspond with the element index).
Would this work for you ?
var dataJson = '[ \
{"range":"Shape","values":[{"idx":0,"val":"Random"},{"idx":1,"val":"Line"},{"idx":2,"val":"Square"},{"idx":3,"val":"Circle"},{"idx":4,"val":"Oval"},{"idx":5,"val":"Egg"}]},\
{"range":"Color","values":[{"idx":0,"val":"Red"},{"idx":1,"val":"Blue"},{"idx":2,"val":"Yellow"},{"idx":3,"val":"Green"},{"idx":4,"val":"Cyan"}]}\
]';
var data = JSON.parse(dataJson);
for (each in data){
if ( (data[each].range) === 'Color'){
for (eachVal in data[each].values){
if (data[each].values[eachVal].val === 'Blue'){
alert(data[each].values[eachVal].idx);
}
}
} ;
}
And here is the JSFiddle for you too.
I have the following code in a display template in sharepoint, I have an array of objects and I need to have the following result.
Name1
Name2
Name3
So I can replace the default rendering of sharepoint multiple people user field with a tooltip.
However, I dont know how to iterate and then concatenate:
Screenshot:
Code:
// List View - Substring Long String Sample
// Muawiyah Shannak , #MuShannak
(function () {
// Create object that have the context information about the field that we want to change it's output render
var projectTeamContext = {};
projectTeamContext.Templates = {};
projectTeamContext.Templates.Fields = {
// Apply the new rendering for Body field on list view
"Project_x0020_Team": { "View": ProjectTeamTemplate }
};
SPClientTemplates.TemplateManager.RegisterTemplateOverrides(projectTeamContext);
})();
// This function provides the rendering logic
function ProjectTeamTemplate(ctx) {
var projectTeamValue = ctx.CurrentItem[ctx.CurrentFieldSchema.Name];
//newBodyvalue should have the list of all display names and it will be rendered as a tooltip automaticlaly
return "<span title='" + projectTeamValue + "'>" + newBodyValue + "</span>";
}
You can "map" property values from the projectTeamValue array objects into a new array, then "join" those values together (using ", " as the separator in this example) all in one go:
var newBodyValue = projectTeamValue.map(function(person) {
return person.value;
}).join(", ");
If your projectTeamValue array looked like:
[{ value: "Name1" }, { value: "Name2" }, { value: "Name3" }]
Then newBodyValue would be:
"Name1, Name2, Name3"
jsFiddle Demo
Side note: Array.prototype.map() was not available in IE 8 and below but should work in every other browser.
I'm new to jQuery. Following is the data variable that contains a json dictionary.
{
"user":null,
"currency":"EUR",
"balance":0,
"translist": [
{ "trans1":"something","trans2":"something2" }
]
}
and my jQuery method receives a json/Javascript object from the Rest GET call
success: function (data){
for(x in data) {
console.log(x + ': ' + data[x]);
}
});
Is there any library that can help to parse/walk through this json object and get to some kind of objects list? I want to check some of the keys and their respective values. Problem is I don't need all the keys and values from the list and also some of the values can be null, which prevented me to apply some solutions I found using SO.
Or usually is it more common to directly start printing the HTML inside the success function?
EDIT:If it was java for example it would be a Map and I would use an iterator to walk through and see/analyse the map values, and create some array list with the values I want from it. What's equivalent of that in jQuery?
If it was java for example it would be a Map and I would use an
iterator to walk through and see/analyse the map values, and create
some arraylist with the values I want in it. What is the equivalent of that
in jQuery?
Any javascript object can be seen as an associative map.
You can for example directly access the currency as data['currency'].
You can also build an array :
var a = [];
for (var key in data) {
a.push({key:key, value:data[key]});
}
You could also build some HTML and apply functions to the data :
$(document.body).append($(
'<table>' + a.map(function(v){
return '<tr><td>'+v.key+'</td><td>'+v.value+'</td></tr>'
}).join('')+'</table>'
));
Demonstration
Using jQuery can make the same iteration simpler (working directly from data) :
$(document.body).append($(
'<table>' + $.map(data, function(value,key){
return '<tr><td>'+key+'</td><td>'+value+'</td></tr>'
}).join('')+'</table>'
));
Demonstration
Try using each
success: function (data){
$.each( data, function( key, value ) {
if(key === "currency")
alert( key + ": " + value );
});
});