Advertisement
If you have a new account but are having problems posting or verifying your account, please email us on hello@boards.ie for help. Thanks :)
Hello all! Please ensure that you are posting a new thread or question in the appropriate forum. The Feedback forum is overwhelmed with questions that are having to be moved elsewhere. If you need help to verify your account contact hello@boards.ie

[Javascript] Getting a JSON string and displaying the data sorted

Options
  • 28-06-2016 11:35am
    #1
    Registered Users Posts: 156 ✭✭


    Hey guys,

    Sorry for the long post.

    I'm creating a website to display a list of library books. I have a JSON string with the books like this:
    [
        {
           "PubAvails": [
            {
              "Publisher": {
                "@Code": "c698",
                "@Name": "Tor"
              },
              "BookAvails": [
                {
                  "@Status": "Available",
                  "Book": {
                    "@PageCount": "542",
                    "@AuthorName": "Robert Jordan",
                    "@CriticRating": "5",
                    "@UserRating": "4",
                    "@Condition": "New",
                    "@Cover": "Hardback",
                    "BookDetails": {
                      "@Name": "Eye Of The World"
                    },
                    "PictureURL": "img1.jpg"
                  },
                  "TotalCharge": {
                    "@RateTotalAmount": "8.98",
                    "@EstimatedTotalAmount": "8.98",
                    "@CurrencyCode": "EUR"
                  }
                },
                {
                  "@Status": "Available",
                  "Book": {
                    "@PageCount": "497",
                    "@AuthorName": "Robert Jordan",
                    "@CriticRating": "5",
                    "@UserRating": "4",
                    "@Condition": "New",
                    "@Cover": "Hardback",
                    "BookDetails": {
                      "@Name": "Shadow Rising"
                    },
                    "PictureURL": "img2.jpg"
                  },
                  "TotalCharge": {
                    "@RateTotalAmount": "9.03",
                    "@EstimatedTotalAmount": "9.03",
                    "@CurrencyCode": "EUR"
                  }
                }
              ]
            },
            {
              "Publisher": {
                "@Code": "a235",
                "@Name": "Rotha"
              },
              "BookAvails": [
                {
                  "@Status": "Available",
                  "Book": {
                    "@PageCount": "298",
                    "@AuthorName": "Dan Brown",
                    "@CriticRating": "5",
                    "@UserRating": "4",
                    "@Condition": "New",
                    "@Cover": "Hardback",
                    "BookDetails": {
                      "@Name": "DaVinci Code"
                    },
                    "PictureURL": "img3.jpg"
                  },
                  "TotalCharge": {
                    "@RateTotalAmount": "6.25",
                    "@EstimatedTotalAmount": "6.25",
                    "@CurrencyCode": "EUR"
                  }
                }
              ]
            }
          ]
        }
    ]
    

    I want to be able to display the data returned from that string on my web page and be able to sort it based on any of the parameters.

    I know you can't sort objects, I need to add each book to an array and sort based on that. What I was thinking of doing was looping through each node of the json, extract the data for each node and then build a book object and add it to an array. That way I can use this code to sort any of the parameters:
    function sortByKey(array, key, direction) {
    		return array.sort(function(a, b) {
    			var x = a[key]; var y = b[key];
    			if (direction == "asc")
    			{
    				return ((x < y) ? -1 : ((x > y) ? 1 : 0));
    			} else {
    				return ((x < y) ? 1 : ((x > y) ? -1 : 0));
    			}
    		});
    	}
    

    The problem is if I was creating a book object with a constructor the above would take 14 arguments which is a bit too messy.

    Note: When I say a "flat" array below, I mean something like the following, I'm not sure if "flat" is the correct word here.
    var books = [
    	{pubCode: "1adf", pubName: "adfa", book: "Test Book"......etc},
    	{pubCode: "2adf", pubName: "adfa", book: "Test Book"......etc},
    ];
    

    So my questions are:

    1. What's the best way to create a "flat" array of objects from this.
    2. Does my array even need to be flat, could I still sort if everything was nested?
    3. Is there a better approach to all this, am I barking up the wrong tree?

    Thanks


Comments

  • Registered Users Posts: 11,262 ✭✭✭✭jester77


    Haven't done any js in years, but this looks like something that could easily be achieved using RxJS, probably flatMap or one of its equivalents is the operator you would need.


  • Registered Users Posts: 2,031 ✭✭✭colm_c


    What you're asking is to sort an array of objects which is totally possible in javascript. Although there will be some performance issues if you try to do it in the browser with 10k+ items in the array.

    Depending on exactly what and how you're building the application, there are many approaches to take - from vanilla js to dom/jquery data table to ember/angular to client/server with some REST services and everything in between.

    Exact solution depends on the problem as well as your skill/experience.


  • Registered Users Posts: 403 ✭✭counterpointaud


    Q1: ES6 destructuring to the rescue
    const extractBooks = data => {
      const result = [];
      data.forEach(entry => {
        entry.PubAvails.forEach(pubAvail => {
          const { ['@Code']: pubCode, ['@Name']: pubName } = pubAvail.Publisher;
          pubAvail.BookAvails.forEach(book => {
            const {
              ['@Status']: status ,
              TotalCharge: {
                ['@RateTotalAmount']: rateTotalAmount,
                ['@EstimatedTotalAmount']: estimatedTotalAmount,
                ['@CurrencyCode']: currencyCode,
              }
            } = book;
            const {
              ['@PageCount'] : pageCount,
              ['@AuthorName']: authorName,
              ['@CriticRating']: criticRating,
              ['@Condition']: condition,
              ['@Cover']: cover,
              BookDetails: {
                ['@Name'] : name
              }
            } = book.Book;
    
            result.push({
              name,
              authorName,
              pageCount,
              pubName,
              pubCode,
              criticRating,
              condition,
              cover,
              status,
              rateTotalAmount,
              estimatedTotalAmount,
              currencyCode
            })
          })
        })
      });
    
      return result;
    };
    


  • Registered Users Posts: 586 ✭✭✭Aswerty


    The main thing that jumps out at me is - you haven't said if you have the data paginated or not.

    Typically, if you have a reasonably large quantity of data that you are displaying to an end user, you'll have this data paginated so that they aren't getting a dump of an entire database table. With this approach you would typically order your data and then you'd take a slice of data (e.g. 20 books) depending on which page the user is on. This would all occur within the DB (i.e. SQL if using MySQL, MS SQL, etc.). So in this situation ordering shouldn't be done on the client side (i.e. with JS). Any time you want to reorder the data for that page you'd hit the DB again since that slice of data will more than likely contain completely different elements.

    A second thing that jumps out at me. Flattening this data (and yes, flat is the correct word) is also something I would typically expect to be done in the DB using Joins. So you'd join your Publisher and Books tables so you get the "flattened" rows back.

    Personally, what I'd do is have the server return a list of available books, already ordered, in a nice flat format, as so:
    [ { "@PublisherCode": "c698",
        "@PublisherName": "Tor",
        "@AuthorName" : "Robert Jordan",
        "@BookName" : "Eye Of The World",
        "@Condition" : "New",
        "@Cover" : "Hardback",
        "@CriticRating" : "5",
        "@CurrencyCode" : "EUR",
        "@EstimatedTotalAmount" : "8.98",
        "@PageCount" : "542",
        "@PictureURL" : "img1.jpg",
        "@RateTotalAmount" : "8.98",
        "@UserRating" : "4"
      },
      { "@PublisherCode": "c698",
        "@PublisherName": "Tor",
        "@AuthorName" : "Robert Jordan",
        "@BookName" : "Shadow Rising",
        "@Condition" : "New",
        "@Cover" : "Hardback",
        "@CriticRating" : "5",
        "@CurrencyCode" : "EUR",
        "@EstimatedTotalAmount" : "9.03",
        "@PageCount" : "497",
        "@PictureURL" : "img2.jpg",
        "@RateTotalAmount" : "9.03",
        "@UserRating" : "4"
      }
    ]
    

    This data can now be easily shoved into a table for display to an end user. I would access the resource through a URL such as example.com/books/available?page=1&sort=publishername. Since this URL is for available books only, there is no need to explicitly state that the book is available in the data (though you could of course keep the availability data in if there was a pressing reason).

    I fully believe the problem you are bumping into is having a poorly designed approach in how you're sending data from the server to the client. This is in turn forcing you to do acrobatics with your data on the client side.


  • Registered Users Posts: 1,029 ✭✭✭John_C


    Peck3277 wrote: »
    So my questions are:

    1. What's the best way to create a "flat" array of objects from this.
    2. Does my array even need to be flat, could I still sort if everything was nested?
    3. Is there a better approach to all this, am I barking up the wrong tree?


    Javascript comes with a set of array functions; map, filter and sort are the ones you'd use. BookAvails looks like it's already an array so there's no issue sorting and filtering it.

    To give you specific answers;
    1. Use array.map to flatten an array
    2. No, there's no need to flatten it. You can work with nested objects.
    3. It really depends on how long the array is. That would determine whether it'd reasonable to manipulate the data on the client.


  • Advertisement
Advertisement