Creating links between nodes d3.js currently returning Uncaught TypeError: Cannot read property 'weight' of undefined
<p>I have the following json structure: </p>

<pre><code>data = {  
           "nodes":[  
              {  
                 "nodeType":"File",
                 "nodeId":16392,
                 "property1":"coint_ctolocal_partitions",
                 "property2":null,
                 "group":0,
                 "more":false
              },
              {  
                 "nodeType":"File",
                 "nodeId":16386,
                 "property1":"pers_contrato_partitions",
                 "property2":null,
                 "group":0,
                 "more":false
              }
           ],
           "links":[  
              {  
                 "source":16386,
                 "target":16392,
                 "value":0,
                 "val":"{\"Contract\":[\"Insurance\"]}",
                 "type":"PTN"
              }
           ]
        }; 
</code></pre>

<p>Currently this is returning <code>Uncaught TypeError: Cannot read property 'weight' of undefined</code>.</p>

<p>In our test data we simply used <code>source:0</code> and <code>target:1</code> and this works as I assume it is using the index of nodes to link the objects together. Or perhaps the <code>linkindex</code> function.</p>

<p>The full function looks like this: </p>

<pre><code>returnTableRelationshipData = function(){

        data = {} // json data as described above  

        // used to store the number of links between two nodes. 
        // mLinkNum[data.links[i].source + "," + data.links[i].target] = data.links[i].linkindex;
        var mLinkNum = {};

        // sort links first
        sortLinks();                                

        // set up linkIndex and linkNumer, because it may possible multiple links share the same source and target node
        setLinkIndexAndNum();

        // check that we don't have empty or null values
        checkDataNotEmpty();

        var w = 600,
            h = 500;

        var force = d3.layout.force()
                    .nodes(d3.values(data.nodes))
                    .links(data.links)
                    .size([w, h])
                    .linkDistance(150)
                    .charge(-300)
                    .on("tick", tick)
                    .start();

        var svg = d3.select(".graphContainer").append("svg:svg")
                    .attr("width", w)
                    .attr("height", h);

        var path = svg.append("svg:g")
                    .selectAll("path")
                    .data(force.links())
                    .enter().append("svg:path")
                    .attr("class", "link");

        var circle = svg.append("svg:g")
                    .selectAll("circle")
                    .data(force.nodes())
                    .enter().append("svg:circle")
                    .attr("r", 6)
                    .call(force.drag);

        var text = svg.append("svg:g")                                
                    .selectAll("g")
                    .data(force.nodes())
                    .enter().append("svg:g");

        // A copy of the text with a thick white stroke for legibility.
        text.append("svg:text")
            .attr("x", 12)
            .attr("y", ".31em")
            .attr("class", "shadow")
            .text(function(d){ return d.property1; });   

        text.append("svg:text")
            .attr("x", 12)
            .attr("y", ".31em")
            .text(function(d){ return d.property1; });

        // Use elliptical arc path segments to doubly-encode directionality.
        function tick() {
            path.attr("d", function(d){
                var dx = d.target.x - d.source.x,
                    dy = d.target.y - d.source.y,
                    dr = Math.sqrt(dx * dx + dy * dy);
                // get the total link numbers between source and target node
                var lTotalLinkNum = mLinkNum[d.source.id + "," + d.target.id] || mLinkNum[d.target.id + "," + d.source.id];
                if(lTotalLinkNum &gt; 1)
                {
                    // if there are multiple links between these two nodes, we need generate different dr for each path
                    dr = dr/(1 + (1/lTotalLinkNum) * (d.linkindex - 1));
                }       
                // generate svg path
                return "M" + d.source.x + "," + d.source.y + 
                    "A" + dr + "," + dr + " 0 0 1," + d.target.x + "," + d.target.y + 
                    "A" + dr + "," + dr + " 0 0 0," + d.source.x + "," + d.source.y;    
            });

            circle.attr("transform", function(d){
                return "translate(" + d.x + "," + d.y + ")";
            });

            text.attr("transform", function(d){
                return "translate(" + d.x + "," + d.y + ")";
            });
        } 

        // sort the links by source, then target
        function sortLinks(){
            if(data.links != null){                         
                data.links.sort(function(a,b){
                    if(a.source &gt; b.source){
                        return 1;
                    }else if(a.source &lt; b.source){
                        return -1;
                    }else{
                        if(a.target &gt; b.target){
                            return 1;
                        }if(a.target &lt; b.target){
                            return -1;
                        }else{
                            return 0;
                        }
                    }
                });
            }
        }

        //any links with duplicate source and target get an incremented 'linknum'
        function setLinkIndexAndNum(){                              
            for(var i = 0; i &lt; data.links.length; i++){
                if(i != 0 &amp;&amp;
                    data.links[i].source == data.links[i-1].source &amp;&amp;
                    data.links[i].target == data.links[i-1].target){
                    data.links[i].linkindex = data.links[i-1].linkindex + 1;
                }else{
                    data.links[i].linkindex = 1;
                }// save the total number of links between two nodes
                if(mLinkNum[data.links[i].target + "," + data.links[i].source] !== undefined){
                    mLinkNum[data.links[i].target + "," + data.links[i].source] = data.links[i].linkindex;
                }else{
                    mLinkNum[data.links[i].source + "," + data.links[i].target] = data.links[i].linkindex;
                }
            }
        }

        function checkDataNotEmpty(){
            data.links.forEach(function(link, index, list) {
                if (typeof link.source === 'undefined') {
                    console.log('undefined link', data.nodes[link.source]);
                }
                if (typeof link.target === 'undefined') {
                    console.log('undefined source', data.nodes[link.target]);
                }
                console.log(typeof link.source, typeof link.target);
            });
        }

}

$(document).ready(function(){
    returnTableRelationshipData();
});
</code></pre>

<p>In the nodes data we have <code>nodeId</code> which identifies the node uniquely. We also have <code>property1</code> which is a unique table name. </p>

<p>So I need some way to set the source and target between the existing data using custom json keys, if this is possible? (ie map nodeId to be source or target). </p>

<p>At first I thought I was getting issues with integers, strings and so on, but we can convert between these if it will help. (I mean I did try this but to no success). </p>

<p>I have made a fiddle here: <a href="https://jsfiddle.net/lharby/j1q1oLzL/1/" rel="nofollow">https://jsfiddle.net/lharby/j1q1oLzL/1/</a></p>