I have a json object like this:
[{
"thing": "Top",
"data": {
"childs": [{
"thing": "a",
"data": {
"text": "sdfgdg1",
"morestuff": {
"thing": "Top",
"data": {
"childs": [{
"thing": "a",
"data": {
"text": "sdfg2",
"morestuff": "",
}
},
{
"thing": "a",
"data": {
"text": "gfhjfghj3",
"morestuff": {
"thing": "Top",
"data": {
"childs": [{
"thing": "a",
"data": {
"text": "asdfsadf 2 4",
"morestuff": {
"thing": "Top",
"data": {
"childs": [{
"thing": "a",
"data": {
"text": "asdfsadf 2 5",
"morestuff": {
"thing": "Top",
"data": {
"childs": {
"thing": "a",
"data": {
"text": "asdfsadf 2 6",
"morestuff": "",
},
"data": {
"text": "asdfsadf 2 6",
"morestuff": "",
}
},
}
},
}
}],
}
},
}
}],
}
},
}
}],
}
},
}
},
{
"thing": "a",
"data": {
"text": "asdfasd1 2",
"morestuff": {
"thing": "Top",
"data": {
"childs": [{
"thing": "a",
"data": {
"text": "asdfsadf 2 3",
"morestuff": "",
}
}],
}
},
}
},
{
"thing": "a",
"data": {
"text": "dfghfdgh 4",
"morestuff": "",
}
}],
}
}]
...and I'm trying to iterate through it and get a total count on the "text" objects.
I can't seem to be able to get something recursive working.. I think I'm missing a base-level understanding of both json and recursion..
After a couple of days of variations on this:
count=0;
c2=0;
c3=0;
function ra(arr){
//console.log(arr.data.morestuff)
if(arr!==undefined && arr.data && arr.data.morestuff===""){
c3++;
}else if((arr && arr.data && typeof arr.data.morestuff==="object")){
if(arr.data.morestuff.data.childs.length>1){
for(var w=0;w<arr.data.morestuff.data.childs.length;w++){
count+=ra(arr.data.morestuff.data.childs[w])
}
}else{
count+=ra(arr.data.morestuff.data.childs[0])
}
}
return(c3)
}
countn=0;//top morestuff with no morestuff
tot=0;
function reps(obj){
tot=obj.data.childs.length;
console.log("tot="+tot)
for(var x=0;x<tot;x++){
tot+=ra(obj.data.childs[x])
c3=0
if(tot>1000){//trying to prevent a runaway loop somehwere
break;
}
}
console.log(tot)
}
reps(json[0]);
I've e to the conclusion that I just don't know. I get all kinds of different results; some have e close by adding together the returns from the ra method, but nothing consistant (i.e. wrong) and always off by at least a few.
The JSON is consistent, though there are un-known numbers of children and childrens children which is why I'm looking to recursion.
Here is a fiddle: /
Ideally, I'd like to count each text object, its' relative position, and the number of children it has, but I figure I can mess with getting that stuff into an array if I could just get the counting working...
NB: I've tried jsonParse and other libraries to no avail. In particular, jsonParse throws an Object has no method "match"
error when trying to use it on this json.
I have a json object like this:
[{
"thing": "Top",
"data": {
"childs": [{
"thing": "a",
"data": {
"text": "sdfgdg1",
"morestuff": {
"thing": "Top",
"data": {
"childs": [{
"thing": "a",
"data": {
"text": "sdfg2",
"morestuff": "",
}
},
{
"thing": "a",
"data": {
"text": "gfhjfghj3",
"morestuff": {
"thing": "Top",
"data": {
"childs": [{
"thing": "a",
"data": {
"text": "asdfsadf 2 4",
"morestuff": {
"thing": "Top",
"data": {
"childs": [{
"thing": "a",
"data": {
"text": "asdfsadf 2 5",
"morestuff": {
"thing": "Top",
"data": {
"childs": {
"thing": "a",
"data": {
"text": "asdfsadf 2 6",
"morestuff": "",
},
"data": {
"text": "asdfsadf 2 6",
"morestuff": "",
}
},
}
},
}
}],
}
},
}
}],
}
},
}
}],
}
},
}
},
{
"thing": "a",
"data": {
"text": "asdfasd1 2",
"morestuff": {
"thing": "Top",
"data": {
"childs": [{
"thing": "a",
"data": {
"text": "asdfsadf 2 3",
"morestuff": "",
}
}],
}
},
}
},
{
"thing": "a",
"data": {
"text": "dfghfdgh 4",
"morestuff": "",
}
}],
}
}]
...and I'm trying to iterate through it and get a total count on the "text" objects.
I can't seem to be able to get something recursive working.. I think I'm missing a base-level understanding of both json and recursion..
After a couple of days of variations on this:
count=0;
c2=0;
c3=0;
function ra(arr){
//console.log(arr.data.morestuff)
if(arr!==undefined && arr.data && arr.data.morestuff===""){
c3++;
}else if((arr && arr.data && typeof arr.data.morestuff==="object")){
if(arr.data.morestuff.data.childs.length>1){
for(var w=0;w<arr.data.morestuff.data.childs.length;w++){
count+=ra(arr.data.morestuff.data.childs[w])
}
}else{
count+=ra(arr.data.morestuff.data.childs[0])
}
}
return(c3)
}
countn=0;//top morestuff with no morestuff
tot=0;
function reps(obj){
tot=obj.data.childs.length;
console.log("tot="+tot)
for(var x=0;x<tot;x++){
tot+=ra(obj.data.childs[x])
c3=0
if(tot>1000){//trying to prevent a runaway loop somehwere
break;
}
}
console.log(tot)
}
reps(json[0]);
I've e to the conclusion that I just don't know. I get all kinds of different results; some have e close by adding together the returns from the ra method, but nothing consistant (i.e. wrong) and always off by at least a few.
The JSON is consistent, though there are un-known numbers of children and childrens children which is why I'm looking to recursion.
Here is a fiddle: http://jsfiddle/CULVx/
Ideally, I'd like to count each text object, its' relative position, and the number of children it has, but I figure I can mess with getting that stuff into an array if I could just get the counting working...
NB: I've tried jsonParse and other libraries to no avail. In particular, jsonParse throws an Object has no method "match"
error when trying to use it on this json.
-
You have two
data
properties in the most nested object - is that correct? – pimvdb Commented Dec 11, 2011 at 17:51 -
@pimvdb yes, but there can be any number of
data
props in any givenmorestuff
property – stormdrain Commented Dec 11, 2011 at 17:56
2 Answers
Reset to default 5If you just want all "text"
properties at any depth, then this should be sufficient: http://jsfiddle/QbpqT/.
You have a property key twice, though ("data"
in the most nested object). Since an object cannot contain two properties with the same key, so you actually have 9 "text"
properties; not 10.
var count = 0;
function iterate(obj) {
for(var key in obj) { // iterate, `key` is the property key
var elem = obj[key]; // `obj[key]` is the value
if(key === "text") { // found "text" property
count++;
}
if(typeof elem === "object") { // is an object (plain object or array),
// so contains children
iterate(elem); // call recursively
}
}
}
iterate(data); // start iterating the topmost element (`data`)
console.log(count); // 9
Here is an answer using object-scan
// const objectScan = require('object-scan');
const data = [{"thing":"Top","data":{"childs":[{"thing":"a","data":{"text":"sdfgdg1","morestuff":{"thing":"Top","data":{"childs":[{"thing":"a","data":{"text":"sdfg2","morestuff":""}},{"thing":"a","data":{"text":"gfhjfghj3","morestuff":{"thing":"Top","data":{"childs":[{"thing":"a","data":{"text":"asdfsadf 2 4","morestuff":{"thing":"Top","data":{"childs":[{"thing":"a","data":{"text":"asdfsadf 2 5","morestuff":{"thing":"Top","data":{"childs":{"thing":"a","data":{"text":"asdfsadf 2 6","morestuff":""}}}}}}]}}}}]}}}}]}}}},{"thing":"a","data":{"text":"asdfasd1 2","morestuff":{"thing":"Top","data":{"childs":[{"thing":"a","data":{"text":"asdfsadf 2 3","morestuff":""}}]}}}},{"thing":"a","data":{"text":"dfghfdgh 4","morestuff":""}}]}}];
const getCount = (obj) => objectScan(['**.text'], { rtn: 'count' })(obj);
console.log(getCount(data));
// => 9
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://bundle.run/[email protected]"></script>
Disclaimer: I'm the author of object-scan