这是绝对可能的,因为 Javascript 为类以及动态类和方法调用提供了完整的反射能力。
JSON 类只是为对象原型提供语法糖,如下所述:(https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes)。但是,还有一个新的反射 API 可以提供帮助,尽管它与之前的 Object 方法非常相似 (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect)。
您可以通过这种方式遍历每个属性并递归转换为 json - 这需要遵守对象属性的“_”前缀约定(您可以轻松修改它以处理带前缀和不带前缀的)。如果您希望使用类的 getter 而不是简单地剥离属性,请参阅底部的示例,使用属性作为指南对类进行类似的动态调用:
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 ) );
}
如果您想以其他方式执行此操作,可以使用此处的解决方案 (Instantiate a JavaScript Object Using a String to Define the Class Name) 从动态名称构造类,并在此处按原样调用对象上的动态方法 (Javascript dynamically invoke object method from string),但这需要保留对于 setter 方法的骆驼大小写的严格命名约定,并在它们应该转换为的类之后命名 json 的属性:
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);
}
(以及How do I make the first letter of a string uppercase in JavaScript? 的首字母大写)
编辑:
如果你想使用 getter 来读取属性而不是直接读取属性,这个例子表明,(我已经走到了这一步,不妨展示它的例子):
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 ) );
}