简体   繁体   中英

How to access JSON data using d3?

I have a JSON data type which I am storing in my model to pass to the view. I also have a bar chart which I would like to use to display the data. However, there are only some fields which I would like to display which are the SupplierName and the Query. I've followed through a d3 tutorial to get the graph but this is the first time I'm putting it into practice.

Does anybody have an idea how to do this?

Controller:

   public ActionResult ValueBySupplierAndClaimType(int ClientID, int ReviewPeriodID, int StatusCategoryID) {
            ValueBySupplierAndClaimTypeViewModel model = new ValueBySupplierAndClaimTypeViewModel {
                ReportData = reportRepo.GetValueBySupplierAndClaimType(ClientID, ReviewPeriodID, StatusCategoryID),
                ReportTitle = "Dashboard Breakdown",
                ReportDescription = "Breakdown for " + reviewRepo.GetAllReviewsByClientID(ClientID).Where(r => r.ReviewID == ReviewPeriodID).Select(r => r.ReviewPeriod).FirstOrDefault()
            };

            model.output = JsonConvert.SerializeObject(model.ReportData, Formatting.Indented);

            return View("ValueBySupplierAndClaimType", model);

JSON:

[  
  {
    "SupplierID": 4336,
    "SupplierName": "Test1",
    "AccountNo": 09579
    "Claim": null,
    "Normal": null,
    "Query": 1000.0000,
    "Formal": null,
    "Strong": null,
    "Unsubstantiated": null
  },
  {
    "SupplierID": 4357,
    "SupplierName": "Test2                 ",
    "AccountNo": 00124
    "Claim": null,
    "Normal": null,
    "Query": 9000.0000,
    "Formal": null,
    "Strong": null,
    "Unsubstantiated": null
  },
  {
    "SupplierID": 4395,
    "SupplierName": "Test3                   ",
    "AccountNo": 00001
    "Claim": null,
    "Normal": null,
    "Query": null,
    "Formal": null,
    "Strong": null,
    "Unsubstantiated": null
  }
]

D3:

 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>

    var margin = { top: 20, right: 20, bottom: 30, left: 40 },
        width = 960 - margin.left - margin.right,
        height = 500 - margin.top - margin.bottom;

    var x = d3.scale.ordinal()
        .rangeRoundBands([0, width], .1);

    var y = d3.scale.linear()
        .range([height, 0]);

    var xAxis = d3.svg.axis()
        .scale(x)
        .orient("bottom");

    var yAxis = d3.svg.axis()
        .scale(y)
        .orient("left")
        .ticks(10, "%");

    var svg = d3.select("body").append("svg")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
      .append("g")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    d3.csv(@Model.output, type, function (error, data) {
        if (error) throw error;

        data.forEach(function(d) {

            //(function(d) {return d.SupplierName})
            //(function(d) {return d.Query})

            x.domain(data.map(function (d) { return d.SupplierName }));
            y.domain([0, d3.max(data, function (d) { return d.Query })]);

        })


        svg.append("g")
            .attr("class", "x axis")
            .attr("transform", "translate(0," + height + ")")
            .call(xAxis);

        svg.append("g")
            .attr("class", "y axis")
            .call(yAxis)
          .append("text")
            .attr("transform", "rotate(-90)")
            .attr("y", 6)
            .attr("dy", ".71em")
            .style("text-anchor", "end")
            .text("Query");

        svg.selectAll(".bar")
            .data(data)
          .enter().append("rect")
            .attr("class", "bar")
            .attr("x", function (d) { return x(d.SupplierName); })
            .attr("width", x.rangeBand())
            .attr("y", function (d) { return y(d.Query); })
            .attr("height", function (d) { return height - y(d.Query); });
    });

    function type(d) {
        d.Query = +d.Query;
        return d;
    }


</script>

I've tried looking at some answers but and have tried to implement them but nothing has seemed to work

There are two problems with your code:

JSON

JsonConvert.SerializeObject() returns a JSON (as the name may indicate) and not an CSV. Therefore you should use d3.json , but

Request

d3.csv and d3.json take an URL as first parameter and fire an XMLHttpRequest to get the data, parse the data when loaded an pass it to the callback.

Your @Model.output holds a string with the full JSON. You don't need to request the data since you already have it as string. You only have to parse the string with JSON.parse() like so:

...
//d3.csv(@Model.output, type, function (error, data) {
try {
  var data = JSON.parse("@Model.output");

  data.forEach(function(d){
    x.domain(data.map(function (d) { return d.SupplierName }));
    y.domain([0, d3.max(data, function (d) { return d.Query })]);
  });
  ...
} catch(e){
  ...
}

Make sure to use try-catch since JSON.parse could fail with an invalid JSON.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM