0

I am using the code below to build a table based on an API and am fine when there is in object in an array (e.g. lineStatuses[0].statusSeverityDescription), however when there is an object, in an object, in an array, it does not work and I get the result [object Object] returned.

Here is a sample of the JSON data from the URL (I am expecting Undefined to be returned for the first record):

[

  {

    "$type": "Tfl.Api.Presentation.Entities.Line, Tfl.Api.Presentation.Entities",

    "id": "bakerloo",

    "name": "Bakerloo",

    "modeName": "tube",

    "disruptions": [],

    "created": "2016-06-03T12:36:54.19Z",

    "modified": "2016-06-03T12:36:54.19Z",

    "lineStatuses": [

      {

        "$type": "Tfl.Api.Presentation.Entities.LineStatus, Tfl.Api.Presentation.Entities",

        "id": 0,

        "statusSeverity": 10,

        "statusSeverityDescription": "Good Service",

        "created": "0001-01-01T00:00:00",

        "validityPeriods": []

      }

    ],

    "routeSections": [],

    "serviceTypes": [

      {

        "$type": "Tfl.Api.Presentation.Entities.LineServiceTypeInfo, Tfl.Api.Presentation.Entities",

        "name": "Regular",

        "uri": "/Line/Route?ids=Bakerloo&serviceTypes=Regular"

      }

    ]

  },

  {

    "$type": "Tfl.Api.Presentation.Entities.Line, Tfl.Api.Presentation.Entities",

    "id": "central",

    "name": "Central",

    "modeName": "tube",

    "disruptions": [],

    "created": "2016-06-03T12:36:54.037Z",

    "modified": "2016-06-03T12:36:54.037Z",

    "lineStatuses": [

      {

        "$type": "Tfl.Api.Presentation.Entities.LineStatus, Tfl.Api.Presentation.Entities",

        "id": 0,

        "lineId": "central",

        "statusSeverity": 5,

        "statusSeverityDescription": "Part Closure",

        "reason": "CENTRAL LINE: Saturday 11 and Sunday 12 June, no service between White City and Ealing Broadway / West Ruislip. This is to enable track replacement work at East Acton and Ruislip Gardens.  Replacement buses operate.",

        "created": "0001-01-01T00:00:00",

        "validityPeriods": [

          {

            "$type": "Tfl.Api.Presentation.Entities.ValidityPeriod, Tfl.Api.Presentation.Entities",

            "fromDate": "2016-06-11T03:30:00Z",

            "toDate": "2016-06-13T01:29:00Z",

            "isNow": false

          }

        ],

        "disruption": {

          "$type": "Tfl.Api.Presentation.Entities.Disruption, Tfl.Api.Presentation.Entities",

          "category": "PlannedWork",

          "categoryDescription": "PlannedWork",

          "description": "CENTRAL LINE: Saturday 11 and Sunday 12 June, no service between White City and Ealing Broadway / West Ruislip. This is to enable track replacement work at East Acton and Ruislip Gardens.  Replacement buses operate.",

          "additionalInfo": "Replacement buses operate as follows:Service A: White City - East Acton - North Acton - West Acton - Ealing Common (for District and Piccadilly Lines) - Ealing BroadwayService B: White City - North Acton - Northolt - South Ruislip - Ruislip Gardens - West RuislipService C: White City - North Acton - Park Royal (Piccadilly Line) - Hanger Lane - Perivale - Greenford - Northolt",

          "created": "2016-05-12T11:04:00Z",

          "affectedRoutes": [],

          "affectedStops": [],

          "isBlocking": true,

          "closureText": "partClosure"

        }

      }

    ],

    "routeSections": [],

    "serviceTypes": [

      {

        "$type": "Tfl.Api.Presentation.Entities.LineServiceTypeInfo, Tfl.Api.Presentation.Entities",

        "name": "Regular",

        "uri": "/Line/Route?ids=Central&serviceTypes=Regular"

      }

    ]

  }

]

I am also trying to use setInterval to refresh the tube-disruption DIV with updated data from the API, which is not workng. Below is the code (with the URL returning some of the JSON data above). Any ideas what I am doing wrong?

var xmlhttp = new XMLHttpRequest();
var url = "https://api.tfl.gov.uk/line/mode/tube/status";

xmlhttp.onreadystatechange=function() {
    if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
        myFunctionDisruption(xmlhttp.responseText);
    }
};

xmlhttp.open("GET", url, true);
xmlhttp.send();

setInterval(myFunctionDisruption, 600000);

function myFunctionDisruption(response) {
    var arr = JSON.parse(response);
    var i;
    var out = "<table>";

    for(i = 0; i < arr.length; i++) {
        out += "<tr><td>" +
        arr[i].lineStatuses[0].disruption.description + <!-- DOES NOT WORK -->
        "</td></tr>";
    }
    out += "</table>";
    document.getElementById("tube-disruption").innerHTML = out;
}

1 Answer 1

0

The below code will generate a table for you. The generic tableMaker function takes an array of an object or an array of multiple objects provided in the first argument. All objects should have same keys (properties) since these keys are used to create the table header (if the second argument is set to true) and the values are used to create each row. It will return an HTML table text. You can see the tableMaker function working with a smaller size data at here. You can also practice it with some sample and simple data you may produce.

In your case you have multiple nested objects those, I guess, need to be converted into separate tables within the corresponding cells of the main table. For that purpose i have another function tabelizer which handles this job recursively by utilizing the tableMaker function. The result of tabelizer is a complete HTML text of your master table.

Lets see

var tableMaker = (o,h) => {var keys = o.length && Object.keys(o[0]),
                           rowMaker = (a,t) => a.reduce((p,c,i,a) => p + (i === a.length-1 ? "<" + t + ">" + c + "</" + t + "></tr>"
                                                                                           : "<" + t + ">" + c + "</" + t + ">"),"<tr>"),
                           rows = o.reduce((r,c) => r + rowMaker(keys.reduce((v,k) => v.concat(c[k]),[]),"td"),h ? rowMaker(keys,"th") : []);
                           return rows.length ? "<table>" + rows + "</table>" : "";
                          },
data = [
  {
    "$type": "Tfl.Api.Presentation.Entities.Line, Tfl.Api.Presentation.Entities",
    "id": "bakerloo",
    "name": "Bakerloo",
    "modeName": "tube",
    "disruptions": [],
    "created": "2016-06-03T12:36:54.19Z",
    "modified": "2016-06-03T12:36:54.19Z",
    "lineStatuses": [
      {
        "$type": "Tfl.Api.Presentation.Entities.LineStatus, Tfl.Api.Presentation.Entities",
        "id": 0,
        "statusSeverity": 10,
        "statusSeverityDescription": "Good Service",
        "created": "0001-01-01T00:00:00",
        "validityPeriods": []
      }
    ],
    "routeSections": [],
    "serviceTypes": [
      {
        "$type": "Tfl.Api.Presentation.Entities.LineServiceTypeInfo, Tfl.Api.Presentation.Entities",
        "name": "Regular",
        "uri": "/Line/Route?ids=Bakerloo&serviceTypes=Regular"
      }
    ]
  },
  {
    "$type": "Tfl.Api.Presentation.Entities.Line, Tfl.Api.Presentation.Entities",
    "id": "central",
    "name": "Central",
    "modeName": "tube",
    "disruptions": [],
    "created": "2016-06-03T12:36:54.037Z",
    "modified": "2016-06-03T12:36:54.037Z",
    "lineStatuses": [
      {
        "$type": "Tfl.Api.Presentation.Entities.LineStatus, Tfl.Api.Presentation.Entities",
        "id": 0,
        "lineId": "central",
        "statusSeverity": 5,
        "statusSeverityDescription": "Part Closure",
        "reason": "CENTRAL LINE: Saturday 11 and Sunday 12 June, no service between White City and Ealing Broadway / West Ruislip. This is to enable track replacement work at East Acton and Ruislip Gardens.  Replacement buses operate.",
        "created": "0001-01-01T00:00:00",
        "validityPeriods": [
          {
            "$type": "Tfl.Api.Presentation.Entities.ValidityPeriod, Tfl.Api.Presentation.Entities",
            "fromDate": "2016-06-11T03:30:00Z",
            "toDate": "2016-06-13T01:29:00Z",
            "isNow": false
          }
        ],
        "disruption": {
          "$type": "Tfl.Api.Presentation.Entities.Disruption, Tfl.Api.Presentation.Entities",
          "category": "PlannedWork",
          "categoryDescription": "PlannedWork",
          "description": "CENTRAL LINE: Saturday 11 and Sunday 12 June, no service between White City and Ealing Broadway / West Ruislip. This is to enable track replacement work at East Acton and Ruislip Gardens.  Replacement buses operate.",
          "additionalInfo": "Replacement buses operate as follows:Service A: White City - East Acton - North Acton - West Acton - Ealing Common (for District and Piccadilly Lines) - Ealing BroadwayService B: White City - North Acton - Northolt - South Ruislip - Ruislip Gardens - West RuislipService C: White City - North Acton - Park Royal (Piccadilly Line) - Hanger Lane - Perivale - Greenford - Northolt",
          "created": "2016-05-12T11:04:00Z",
          "affectedRoutes": [],
          "affectedStops": [],
          "isBlocking": true,
          "closureText": "partClosure"
        }
      }
    ],
    "routeSections": [],
    "serviceTypes": [
      {
        "$type": "Tfl.Api.Presentation.Entities.LineServiceTypeInfo, Tfl.Api.Presentation.Entities",
        "name": "Regular",
        "uri": "/Line/Route?ids=Central&serviceTypes=Regular"
      }
    ]
  }
],
tabelizer = (a) => a.length ? tableMaker(a.map(e => Object.keys(e).reduce((p,k) => (p[k] = Array.isArray(e[k]) ? tabelizer(e[k]) : e[k],p),{})),true)
                            : "",
tableHTML = tabelizer(data);
                            
document.write(tableHTML);

I used arrow functions but they might not work at Safari or IE. You might need to convert them to the conventional function notation.

You can also try the code out at repl.it where you can see the HTML text displayed through console.log.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.