Reputation:
I have the following JavaScript classes
class Driver {
constructor() {
this._name = null;
this._car = null;
}
setName(name) {
this._name = name;
}
getName() {
return this._name;
}
setCar(car) {
this._car = car;
}
getCar() {
return this._car;
}
}
class Car {
constructor() {
this._model = null;
}
setModel(model) {
this._model = model;
}
getModel(model) {
return this._model;
}
}
And I want to solve two problems:
{name:"Boo", car:{model:"Foo"}}
I want to get driver object of Driver class with car object of Car class.{name:"Boo", car:{model:"Foo"}}
.Is it possible to do automatically? I mean without writing code for every field of every class?
Upvotes: 2
Views: 822
Reputation: 1429
This is absolutely possible since Javascript provides full reflection capabilities for classes and dynamic class and method invocation.
JSON classes simply provide syntactic sugar over the object prototyping as noted here: (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes). But, there is also a new reflection API that can help, though it is very similar to the Object methods from before (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect).
You can iterate over each property and convert to json recursively this way-- which requires holding to the convention of '_' prefixes for properties of the object (you could easily modify it to handle both prefixed and unprefixed). If you instead want to use the getters for the class instead of simply stripping the properties, see the example at the bottom using a similar dynamic invocation on the class using the properties as a guide:
function transformUnderscoreProperties(object)
{
var returnable = {};
for (var property in object) {
if (object.hasOwnProperty(property)) {
if(property.charAt(0) === '_'){
let name = property.substr(1); //Property name without _
if( typeof object[property] === 'object' )
{
returnable[name] = transformUnderscoreProperties( object[property] );
}
else returnable[name] = object[property];
}
}
}
return returnable;
}
function recursiveObjectStringify( object ) {
return JSON.stringify( transformUnderscoreProperties( object ) );
}
If you want to do it the other way, you can construct classes from dynamic name using the solution here (Instantiate a JavaScript Object Using a String to Define the Class Name), and call dynamic methods on the object as is here (Javascript dynamically invoke object method from string), but this requires keeping to a strict naming convention of camel case for setter methods and naming the properties of the json after the class to which they should be transformed:
function classFromObject( object, className ){
className = capitalizeFirstLetter( className );
var returnable = window[className];
for (var property in object ) {
if (object.hasOwnProperty(property)) {
if( typeof object[property] === "object" ){
returnable["set"+capitalizeFirstLetter(property)]( classFromObject( object[property], property ) ); //Calls "setCar()" on the object returned from the car being made into a class
}
else
returnable["set"+capitalizeFirstLetter(property)]( object[property] ); //Calls "setName()" on the object with the property value.
}
}
return returnable;
}
function capitalizeFirstLetter(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}
(and a shoutout to How do I make the first letter of a string uppercase in JavaScript? for the first letter capitalization)
EDIT: If you want to use the getters in reading the properties instead of just reading the properties directly, this example shows that, (I've come this far, might as well show the example for it):
function transformUnderscorePropertiesGetters(object)
{
var returnable = {};
for (var property in object) {
if (object.hasOwnProperty(property)) {
if(property.charAt(0) === '_'){
let name = property.substr(1); //Property name without _
if( typeof object[property] === 'object' )
{
returnable[name] = transformUnderscoreProperties( object["get" + capitalizeFirstLetter](name) );
}
else returnable[name] = object["get" + capitalizeFirstLetter](name)();
}
}
}
return returnable;
}
function recursiveObjectStringifyGetters( object ) {
return JSON.stringify( transformUnderscorePropertiesGetters( object ) );
}
Upvotes: 1