mohsen1 / json-formatter

Angular directive for collapsible JSON in HTML
http://azimi.me/json-formatter/demo/demo.html
Other
372 stars 85 forks source link

Provision to pass custom name to the json object. #32

Closed karthilxg closed 9 years ago

karthilxg commented 9 years ago

I have an use case to rename the default Object constructor name to some custom name.

person1 = {
    name: 'Mohsen',
    age: '25',
    job: {
      occupation: 'Software Engineer',
      company: 'abcd',
      role: 'Manager'
    }
  }
<json-formatter open="1" json='person1.job' custom-name="Employee"></json-formatter>

I know using the below style would create the custom constructor, since I'm reading the data from API response and passing the json response directly to the directive, so I wanted to explicitly set the custom name property to rename the default Object constructor name.

 function Person(name){ this.name = name; }
 $scope.person = new Person('Mohsen');
mohsen1 commented 9 years ago

But it will only work for one level. You can override __proto__.constructor to achieve the same result.

var obj = {};
obj.__proto__ = {constructor: function CustomConstructor() {}};
screen shot 2015-09-10 at 10 17 00 am

With __proto__ you are not limited to one level. You can add custom constructors to deeper levels:

obj.foo = {__proto__: {constructor: function Foo(){}}};
screen shot 2015-09-10 at 10 18 50 am
mohsen1 commented 9 years ago

Sorry closed by mistake

karthilxg commented 9 years ago

@mohsen1 Thanks for your quick response, I understand we can use prototype property to add constructor names to all levels in an object, but my use case is little different that I need to fetch the API response (ex: array of objects) and pass it to ng-repeat to list down all the objects.

I would like not to iterate the array from the API response to add the __proto__ prototype to the individual objects prior passing it to the ng-repeat, let me know your thoughts.

View

    <div class="result">
      <ol>
        <li ng-repeat="person in people track by person.name">
          <json-formatter open="1" json='person' custom-name="Employee - {{person.name}}"></json-formatter>
        </li>
      </ol>
    </div>

Output

json-git1

Sample API Response

[{

        name: 'Mohsen',
        age: '25',
        job: {
            occupation: 'Software Engineer',
            company: 'abcd',
            role: 'Manager'
        }
    },
    {

        name: 'Karthick',
        age: '25',
        job: {
            occupation: 'Software Engineer1',
            company: 'abcd',
            role: 'Manager'
        }
    },
    {

        name: 'Jordan',
        age: '25',
        job: {
            occupation: 'Software Engineer2',
            company: 'abcd',
            role: 'Manager'
        }
    },
    {

        name: 'Sachin',
        age: '25',
        job: {
            occupation: 'Software Engineer3',
            company: 'abcd',
            role: 'Manager'
        }
    }]
mohsen1 commented 9 years ago

It would be possible to use a helper function to do the job for you

    <div class="result">
      <ol>
        <li ng-repeat="person in people track by person.name">
          <json-formatter open="1" json='addContructorName(person, "Employee - " + person.name)'></json-formatter>
        </li>
      </ol>
    </div>
function addContructorName(obj, name) {
 obj.__proto__.constructor = name;
 return obj;
}

Your case is a bit ad-hoc and I don't believe this is something a lot of people will want. You can either your your own fork as a dependency or use the method I suggested.

karthilxg commented 9 years ago

@mohsen1 Ok, sounds good, helper function should work for my case.

mohsen1 commented 9 years ago

Good to know! Thanks!

cozyazure commented 8 years ago

Most of the time, the constructor is using an anonymous function rather than a named one. In es6, the constructor in proto has the property of name. When a new Object() is called, the constructor's name will be assigned automatically. Was thinking if we can do something like this?

    if (object.__proto__ && object.__proto__constructor && object.__proto__constructor.name) {
        return object.__proto__.constructor.name;
    } 

That's more intuitive, after-all the custom name of the object IS the class name.

Any comments? If all is good, I am willing to do a PR

mohsen1 commented 8 years ago

Yeah, if you create a pr we can discuss it there further