【问题标题】:Problems with parsing JSON for D3为 D3 解析 JSON 的问题
【发布时间】:2016-08-02 20:51:57
【问题描述】:

我正在使用 Flask 和 Python 构建一个应用程序,并且我想将一些 Python 生成的结果传递到 JSON 中,以便它们可以在容器流体下使用 D3 进行可视化。为此,我尝试使用 Jinja 方法var myjson = {{jsonDict|tojson }};。这里jsonDict 是我的Python 代码中的一个变量,它是一个dict 字符串,其中单引号已替换为带有正则表达式的双引号,因此它看起来像正确的JSON。我也在用JS方法root = JSON.parse( myjson );。我相信这两者的结合应该可以解决我的问题,但是当我运行代码时,我得到了错误:

(index):2222    
Uncaught SyntaxError: Unexpected token y in JSON at position 0 
uo  @   d3.v3.min.js:3
i   @   d3.v3.min.js:1

这是我尝试使用的 D3 模板: http://bl.ocks.org/mbostock/7607535

这是我对这个 D3 的实现(只是相关脚本):

<script>

var margin = 20,
    diameter = 960;

var color = d3.scale.linear()
    .domain([-1, 5])
    .range(["hsl(152,80%,80%)", "hsl(228,30%,40%)"])
    .interpolate(d3.interpolateHcl);

var pack = d3.layout.pack()
    .padding(2)
    .size([diameter - margin, diameter - margin])
    .value(function(d) { return d.size; })

var svg = d3.select("#dan").append("svg") //#dan is name of my container fluid
    .attr("width", diameter)
    .attr("height", diameter)
  .append("g")
    .attr("transform", "translate(" + diameter / 2 + "," + diameter / 2 + ")");

//this is the part of the code I have added //
var myjson = {{ jsonDict|tojson }};
root = JSON.parse( myjson );
//this is the part of the code I have added //    

d3.json("root", function(error, root) {
  if (error) throw error; //this is index 2222

  var focus = root,
      nodes = pack.nodes(root),
      view;

  var circle = svg.selectAll("circle")
      .data(nodes)
    .enter().append("circle")
      .attr("class", function(d) { return d.parent ? d.children ? "node" : "node node--leaf" : "node node--root"; })
      .style("fill", function(d) { return d.children ? color(d.depth) : null; })
      .on("click", function(d) { if (focus !== d) zoom(d), d3.event.stopPropagation(); });

  var text = svg.selectAll("text")
      .data(nodes)
    .enter().append("text")
      .attr("class", "label")
      .style("fill-opacity", function(d) { return d.parent === root ? 1 : 0; })
      .style("display", function(d) { return d.parent === root ? "inline" : "none"; })
      .text(function(d) { return d.name; });

  var node = svg.selectAll("circle,text");

  d3.select("#dan")
      .style("background", color(-1))
      .on("click", function() { zoom(root); });

  zoomTo([root.x, root.y, root.r * 2 + margin]);

  function zoom(d) {
    var focus0 = focus; focus = d;

    var transition = d3.transition()
        .duration(d3.event.altKey ? 7500 : 750)
        .tween("zoom", function(d) {
          var i = d3.interpolateZoom(view, [focus.x, focus.y, focus.r * 2 + margin]);
          return function(t) { zoomTo(i(t)); };
        });

    transition.selectAll("text")
      .filter(function(d) { return d.parent === focus || this.style.display === "inline"; })
        .style("fill-opacity", function(d) { return d.parent === focus ? 1 : 0; })
        .each("start", function(d) { if (d.parent === focus) this.style.display = "inline"; })
        .each("end", function(d) { if (d.parent !== focus) this.style.display = "none"; });
  }

  function zoomTo(v) {
    var k = diameter / v[2]; view = v;
    node.attr("transform", function(d) { return "translate(" + (d.x - v[0]) * k + "," + (d.y - v[1]) * k + ")"; });
    circle.attr("r", function(d) { return d.r * k; });
  }
});

d3.select(self.frameElement).style("height", diameter + "px");

</script>

如你所见,我从 D3 代码中替换了原来的 JS 行:

d3.json("flare.json", function(error, root) {
  if (error) throw error;

与:

var myjson = {{ jsonDict|tojson }};
    root = JSON.parse( myjson );   

    d3.json("root", function(error, root) {

由于我现在有我的代码,如果我检查页面,svg 会显示在网页上的正确位置,但它是空白的。

我是 D3 和 Javascript 的新手。任何帮助将非常感激!谢谢!

编辑 - 控制台日志

如果我执行 console.log(myjson),控制台会正确打印 JSON 字符串(见下文)

如果我执行 console.log(root),控制台会打印

Object {children: Array[2], name: "flare"}
children:Array[2]
name:"flare"
__proto__:Object
__defineSetter__: __defineSetter__()
__lookupGetter__:__lookupGetter__()
__lookupSetter__:__lookupSetter__()
constructor:Object()
hasOwnProperty:hasOwnProperty()
isPrototypeOf:isPrototypeOf()
propertyIsEnumerable:propertyIsEnumerable()
toLocaleString:toLocaleString()
toString:toString()
valueOf:valueOf()
get __proto__:__proto__()
set __proto__:__proto__()

所以看来JSON.parse 方法在某种程度上让我失望了。

编辑——我的 JSON 字符串从 Python 传递到 var myjson

{"name": "flare", "children": [{"name": "concept0", "children": [{"name": "intermediate host", "size": 700}, {"name": "abstrusus brevior", "size": 700}, {"name": "stage larva", "size": 700}, {"name": "anterior extremity", "size": 700}, {"name": "crenosoma vulpi", "size": 700}]}, {"name": "concept1", "children": [{"name": "infected cat", "size": 700}, {"name": "abstrusus infection", "size": 700}, {"name": "domestic cat", "size": 700}, {"name": "feline aelurostrongylosis", "size": 700}, {"name": "cat infect", "size": 700}]}]}

console.log(myjson) 的页面源

{"name": "flare", "children": [{"name": "concept0", "children": [{"size": 700, "name": "intermediate host"}, {"size": 700, "name": "abstrusus brevior"}, {"size": 700, "name": "stage larva"}, {"size": 700, "name": "anterior extremity"}, {"size": 700, "name": "crenosoma vulpi"}]}, {"name": "concept1", "children": [{"size": 700, "name": "infected cat"}, {"size": 700, "name": "abstrusus infection"}, {"size": 700, "name": "domestic cat"}, {"size": 700, "name": "feline aelurostrongylosis"}, {"size": 700, "name": "cat infect"}]}]}

编辑 - 我认为问题可以在 console.log(root) 中看到。我检查了其他 D3 可视化,日志通常应如下所示:

Object {name: "flare", children: Array[5]}
children: Array[5]
depth:0
name:"flare"
r:470
value:21000
x:470
y:470
__proto__:Object

【问题讨论】:

  • 使用console.log(root) 查看您使用的任何浏览器的开发者控制台中的root 是什么。验证您的 root 是正确的 JSON,并且是 D3 所期望的正确格式。
  • @SnarkShark 谢谢 - 这正是它在页面源代码中列出的方式吗?您介意复制以var myjson = 开头的输出行吗?
  • 您在 jinja 模板中使用了tojson()此函数将给定对象转换为 JSON 表示形式。 那么为什么之后需要使用JSON.parse()?不能直接传myjson吗?
  • d3.json 以 url 作为其参数,本质上它是一个 ajax 请求,但您已经有您的数据,所以不需要调用它。尝试在没有 d3.json() 函数的情况下运行您的代码
  • @Craicerjack,如果您愿意,您可以复制/粘贴您对 d3.json() 函数的回复作为对我问题的回答,这样我就可以接受它作为最佳答案,而您回答问题将获得荣誉:)

标签: javascript python json d3.js flask


【解决方案1】:

因为您已经通过烧瓶应用程序将 json 传递给客户端,所以无需使用 d3 的 d3.json() 方法。 d3.json() 本质上是一个 ajax GET 请求,它从服务器请求文件。

d3.json(url[, 回调])

使用 mime 在指定 url 创建对 JSON 文件的请求 输入“应用程序/json”。如果指定了回调,则请求为 立即使用 GET 方法发出,回调将是 文件加载或请求失败时异步调用; 使用两个参数调用回调:错误(如果有)和 解析的 JSON。如果发生错误,解析的 JSON 是未定义的。如果不 指定回调,返回的请求可以使用 xhr.get 或类似的,并使用 xhr.on 处理。

您已经将数据存储在 javascript 中的变量中,因此无需从服务器请求它。
此外,当您尝试请求它时,您传递的网址无效。
删除 d3.json() 函数并运行其余代码应该可以工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多