user4513271
user4513271

Reputation:

Mapping JSON to ES6 Classes

I have our staff in a json file, and had the idea to use that data with ES6 classes. The more I work with this, the more I feel as though I may be missing something. I had this working in coffeescript as such:

fetch  = require('node-fetch')
domain = 'domain.com'
apiSrc = 'api.domain.com'
slug   = 'people'

class Person
  constructor: (json) -> {name: @name, title: @title, school: @school, bio: @bio} = json
  email: (username) ->
    username.replace(/\s/, '.').toLowerCase() + '@' + domain
  profile: ->
    content = []
    if this.name   then content.push("#{@name}")
    if this.title  then content.push("#{@title}")
    if this.school then content.push(school) for school in "#{@school}"
    if this.bio    then content.push("#{@bio}")
    if this.name   then content.push(this.email("#{@name}"))
    content.join('')

fetch('http://' + apiSrc + '/' + slug + '.json')
  .then((response) -> response.json())
  .then((api) ->
    content = []
    group   = []
    group.push(new Person(them)) for them in api[slug]
    for them, index in group
      content.push(them.profile())
      console.log(content.join(''))
  )

But then I thought it would be even better if I could convert it to ES6. I know the use case is simple, and classes certainly aren't necessary, since I'm just using the data for templating, however, for the sake of learning, I was attempt to do this. Am I going about this the wrong way? Right now, I feel like there should be a way to return all of the "people" that I put into the Person class. However, the only way I could figure out how to do that was to run a for loop and then write it to the document.

class Person {
  constructor(data) { ({name: this.name, title: this.title, school: this.school, bio: this.bio, email: email(this.name)} = data); }
  email(username) {
    return username.replace(/\s/, '.').toLowerCase() + '@' + location.hostname.replace(/[^\.\/\@]+\.[^\.\/]+$/, '');
  }
  profile() {
    return `${this.name} ${this.title}`;
  }
}

var apiSrc = 'api.domain.com';
var slug   = 'people';
fetch(`http://${apiSrc}/${slug}.json`)
  .then(function(response) { return response.json() }) // .then(response => response.json())
  .then(function(api) {
    var content = [];
    var group = [];
    for (var i = 0; i < api[slug].length; i++) { var them = api[slug][i]; new Person(them); }
    for (var i = 0; index < group.length; i++) {
      var them = group[i];
      content.push(them.profile());
      console.log(content.join(''));
    }
  });

My ES6 conversion actually isn't even working right now. API returns the JSON but after that it gets messed up. Any suggestions would be really helpful as I'm trying to better myself as a coder and hope this sort of example could help others learn Classes in a real use case.

Upvotes: 5

Views: 9933

Answers (1)

Joe Hildebrand
Joe Hildebrand

Reputation: 10414

You might try using the reviver parameter of JSON.parse. Here is a simplified example:

class Person {
  // Destructure the JSON object into the parameters with defaults
  constructor ({name, title, school=[]}) {
    this.name = name
    this.title = title
    this.school = school
  }
}

var api = JSON.parse(a, function (k,v) {
  // Is this a new object being pushed into the top-level array?
  if (Array.isArray(this) && v.name) {
    return new Person(v)
  }
  return v
})

var group = api["people/administration"]

Upvotes: 7

Related Questions