简体   繁体   中英

JSON: return whole matching array from an object

I have a JSON file for API. This will serve the static content for my next personal website:

[
  {
    "articles": [
      {
        "_id": "0",
        "url": "audrey-hepburn",
        "title": "Audrey Hepburn",
        "category": "foo",
        "body": "Nothing is impossible, the word itself says 'I'm possible'!",
        "tags": [ "foo" ]
      },
      {
        "_id": "1",
        "url": "walt-disney",
        "title": "Walt Disney",
        "category": "foo",
        "body": "You may not realize it when it happens, but a kick in the teeth may be the best thing in the world for you.",
        "tags": [ "foo", "bar" ]
      },
      {
        "_id": "2",
        "url": "unknown",
        "title": "Unknown",
        "category": "bar",
        "body": "Even the greatest was once a beginner. Don't be afraid to take that first step.",
        "tags": [ "foo", "bar", "baz" ]
      },
      {
        "_id": "3",
        "url": "neale-donald-walsch",
        "title": "Neale Donald Walsch",
        "category": "bar",
        "body": "You are afraid to die, and you're afraid to live. What a way to exist.",
        "tags": [ "foo", "bar", "baz" ]
      },
      {
        "_id": "4",
        "url": "test",
        "title": "Test Article",
        "category": "bar",
        "body": "This is a test article.",
        "tags": [ "foo", "bar", "baz", "bam" ]
      }
    ]
  },
  {
    "users": [
      { "name": "Admin" },
      { "name": "User" }
    ]
  }
]

This JSON file is called by this API:

/////////////////////////////////////////////////////////////
// GRABS EVERY ARTICLES PER PAGES BY LATEST
// http://127.0.0.1:3000/api/articles/page/0/2/order/adddate/auth/<API-TOKEN>
/////////////////////////////////////////////////////////////

router.get('/articles/page/:start/:end/order/:order/auth/:token', function(req, res) {
  fsAsync(function(err, data) {
    if (err) {
      return res.send(err);
    }

    if(req.params.order === 'adddate') {
      var articles = data[0].articles.reverse();
    }
    else {
      var articles = data[0].articles;
    }

    var start = req.params.start;
    var end = req.params.end;
    var slice = articles.slice(start, end);

    var q = slice.filter(function (article) {
      return article && apiToken === req.params.token;
    });
    res.json(q);
  });
});

/////////////////////////////////////////////////////////////
// GRABS SINGLE ARTICLE BY URL
// http://127.0.0.1:3000/api/articles/url/foo/auth/<API-TOKEN>
// Match any field like "url" and not just the index "id"
/////////////////////////////////////////////////////////////

router.get('/articles/url/:id/auth/:token', function(req, res) {
  fsAsync(function(err, data) {
    if (err) {
      return res.send(err);
    }
    var articles = data[0].articles;
    var q = articles.filter(function (article) {
      // return article.id === req.params.id;
      return article.url === req.params.id && apiToken === req.params.token;
    });
    res.json(q[0]);
  });
});

Router for a single blog post, which is using the url api when I making request for a single blog post with http://domain.com/journal/audrey-hepburn URL:

router.get('/:url', function(req, res, next) {
  var URL = req.params.url;
  console.log(URL);

  var reqURL = req.protocol + '://' + req.hostname + ':' + usedPort + '/api/articles/url/' + URL + '/auth/' + apiToken;

  request(reqURL, function (error, response, body) {
    console.log(JSON.parse(body));
    var articles = JSON.parse(body);
    res.render('blog-article', {
      layout: 'main',
      data: articles
    });
  })
});

handlebar template for a single blog post:

<article class="id-{{data._id}}">
  <h1><a href="/journal/{{data.url}}">{{data.title}}</a></h1>
  <div class="category"><a href="/category/{{data.category}}">{{data.category}}</a></div>
  <p>{{data.body}}</p>
  <div class="tags">
    <ul>
      {{#each data.tags}}
      <li><a href="/tags/{{this}}">{{this}}</a></li>
      {{/each}}
    </ul>
  </div>
</article>

For example if I want I visit my http://domain.com/journal/audrey-hepburn URL when I want to see the Audrey Hepburn ? I use this solution.

My question is how I modify the router IF there's no any URL router solution, just only the first solution which is grabbing every article array into a single object in the JSON file?

Of course, the easiest would be if I creating an object for every article array with the name of it's _id or url , but unfortunately I want to use this template for future sites with external apis and not every api separating their post contents with unique identifiers, instead following the same route, having the request in the same object with other arrays.

Thank You for your help!

SOLUTION (Thank You for ShanShan):

var db = '/../public/articles/data.json';
var data = require(__dirname + db);

router.get('/:url', function (req, res, next) {
  var articles = data[0].articles;
  var url = req.params.url;

  var selectedArticle = articles.find(function(article) {
      return article.url === url;
  });

  console.log(selectedArticle);

  res.render('blog-article', {
    layout: 'main',
    data: selectedArticle
  });
});

You already know how to create a route, you only need to filter the articles:

router.get('/journal/:url', function (req, res, next) {
    fsAsync(function (err, data) {
        var articles = data[0].articles;
        var url = req.params.url;

        // this will get you the first article matching the url
        var selectedArticle = articles.find(function(article) {
            return article.url == url;
        });

        // render your page with selectedArticle

    });
});

On a side note, if your JSON file isn't changed by your app or doesn't change often, you can load it once and for all with require instead of reading the file again and again:

// data is an object
var data = require(__dirname + db);

router.get('', function (req, res, next) {
    var articles = data[0].articles;
    // ...
});

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