1

I've been trying to convert JSON like this into something that d3 can work with but I have been having a bit of trouble. Here's the example JSON

[{
    "name" : "MATH210",
    "work" : {
        "assessment1" : {
            "mark" : 65,
            "weight" : 40
        },
        "assessment2" : {
            "mark" : 65,
            "weight" : 60
        }
    },
    "overallMark" : 95
},
{
    "name" : "MATH215",
    "work" : {
        "assessment1" : {
            "mark" : 67,
            "weight" : 30
        },
        "assessment2" : {
            "mark" : 65,
            "weight" : 45
        },
        "exam" : {
            "mark" : 72,
            "weight" : 25
        }
    },
    "overallMark" : 85
},
{
            "name" : "MATH220",
        "work" : {
        "assessment1" : {
            "mark" : 65,
            "weight" : 50
        },
        "assessment2" : {
            "mark" : 65,
            "weight" : 50
        }
    },
    "overallMark" : 75
    }]

I'm quite new to d3 but all the examples I've read and worked through have had data in the form of arrays so that's what my first approach focused on.

I'll post a little bit of code so you can better understand what I've done. So I first create an array containing module objects from the JSON using code like this

var count = 0;

// loop through json and instantiate each
// module and store in the modules array
$.each(json, function(i, item) {

    progress.modules[count] = new Module( i , item );
    count++;

});

Then I use lots of nested for/in loops to extract the data I want and store them in lots of arrays for each module, each module has 3 different arrays.

// Arrays that will hold all the broken down data
this.workNames = [], this.marks = [], this.weights = [];

This approach works but won't be appropriate for a lot of data.

All I want to do is draw some pie graphs based on overall marks and their weights and a scatter graph. From what I have read elsewhere on stack overflow and across the web I have a feeling that there is a much more graceful way to take this data and transform it into something that d3 can work with.

Maybe by using d3.nest() like this

D3 JSON data conversion

Does anybody have any ideas how I can transform this JSON to work well with d3 without using the approach above?

Thanks in advance :)

Community
  • 1
  • 1
Connor Atherton
  • 161
  • 3
  • 11
  • Put your code in json lint and verify it.If its error free than the conventional method is good enough.. `d3.json("data.js", function(data) { alert(data.length) });`...if you find error than modify it – HIRA THAKUR Jul 28 '13 at 21:05

2 Answers2

3

Let's look at a sub-task of the overall conversion. Consider this bit of data you have, which is in the form of an object (aka hash) of objects:

{
    "assessment1" : {
        "mark" : 67,
        "weight" : 30
    },
    "assessment2" : {
        "mark" : 65,
        "weight" : 45
    },
    "exam" : {
        "mark" : 72,
        "weight" : 25
    }
}

Most likely, what you want to transform it into is this array of objects:

[
    {
        "id": "assessment1"
        "mark" : 67,
        "weight" : 30
    },
    {
        "id": "assessment2"
        "mark" : 65,
        "weight" : 45
    },
    {
        "id" : "exam"
        "mark" : 72,
        "weight" : 25
    }
]

So, if the original data was assigned to a var named work, then this is how you'd turn it into the array:

var workAsArray = []; // This will be the resulting array
for(var key in work) {
  var entry = work[key]; // This will be each of the three graded things
  entry.id = key; // e.g. "id": "assessment1"
  workAsArray.push(entry)
}

This approach could also apply to the outer layer of data that contains this "work" array, and then the code snippet from above would be nested inside an outer loop.

Hope this helps....

P.S.

d3.nest is not going to help you in this case because it does sort of the opposite of what you're asking. It helps convert an array of data into a hash.

meetamit
  • 24,727
  • 9
  • 57
  • 68
  • Thanks for this man. About an hour after I posted this question I done exactly this, I converted all the work objects into arrays so d3 could work with them, but still thanks for answering. Reassures me that I took the right approach :) – Connor Atherton Jul 29 '13 at 22:04
0

Here is a small converter that I made it changes any JSON to d3 format:

<!DOCTYPE html>
<html>
<body>
<p id="demo"></p>
<script>

//Eample JSON
var complexJson = {
"problems": [{
    "Diabetes":[{
        "medications":[{
            "medicationsClasses":[{
                "className":[{
                    "associatedDrug":[{
                        "name":"asprin",
                        "dose":"",
                        "strength":"500 mg"
                    }],
                    "associatedDrug#2":[{
                        "name":"somethingElse",
                        "dose":69,
                        "strength":"500 mg"
                    }]
                }],
                "className2":[{
                    "associatedDrug":[{
                        "name":"asprin",
                        "dose":"",
                        "strength":"500 mg"
                    }],
                    "associatedDrug#2":[{
                        "name":"somethingElse",
                        "dose":"",
                        "strength":"500 mg"
                    }]
                }]
            }]
        }],
        "labs":[{
            "missing_field": "missing_value",
            "boolean_field": true
        }]
    }],
    "Asthma":[{}]
}]};

//Test if we should dig deeper
function hasJsonStructure(str) {
    if (typeof str === 'string') return false;
    try {
        return Object.prototype.toString.call(str) === '[object Object]' || Array.isArray(str);
    } catch (err) {
        return false;
    }
};


//Parse and convert object recursive
function walk2(obj2,level) {
    var mytempCH = [];
    var outer = [];
    for (var key in obj2){
        var value = obj2[key];
        if(hasJsonStructure(value)){
            //has children
            var mytempCH2 = new Object();
            mytempCH2.name = key;
            mytempCH2.children = walk2(value,level+1);
            outer.push(mytempCH2);
        }else{
            outer.push({"name": key + ": " + value, "value": level})
        }
      }
      return outer
}

//Preapare Object Root
var myNewObj = new Object();
myNewObj.name = "ConvertedObj";
myNewObj.children = [];
var level = 1;
//Start work
myNewObj.children = walk2(complexJson,1);

//Output text to html
document.getElementById("demo").innerHTML = JSON.stringify(myNewObj); + "<br>";;
</script>

</body>
</html>
stawiu
  • 21
  • 3