在 Javascript 中反序列化多态 JSON

Rod*_*ddy 5 javascript polymorphism json

我的客户端代码从服务器获取一个 JSON“对象”,然后解析它。解析的对象包含一个“type”属性,该属性应该控制对象的类。

$.getJSON("foo.json").done(function(data, textStatus, xhr) {
    $.each(data.objects, function(key, val)
    {
      if (val.type = "A") // make val into an object of class A, somehow?
        ...
      else if (val.type = "B") // make val into an object of class B somehow?
        ... etc...
    }
}    
Run Code Online (Sandbox Code Playgroud)

如何创建正确类型的 JavaScript 对象而不显式复制每个属性,或者将解析的对象转换为不同的类型?

我读过一些关于__proto__但感觉它是一个大锤,而本来应该是一个小坚果......

我见过关于 Java 和 Jackson 的类似问题,但没有看到关于 Javascript 的问题......

Cha*_*ira 5

你可以做这样的事情

function ObjectFactory() {
    this.newInstance = function(val) {
      if (val.type == "A") return new A(val);
      if (val.type == "B") return new B(val);
    }
}    
function A(data) {
    // do something with the data
    this.property = data.property;
}

function B(data) {
    // do something with the data
    this.property = data.property;
    this.bSpecificProperty = data.bSpecificProperty;
}

$.getJSON("foo.json").done(function(data, textStatus, xhr) {
    var objectFactory = new ObjectFactory();
    var objects = $.map(data.objects, objectFactory.newInstance);

    console.log(objects);
}   
Run Code Online (Sandbox Code Playgroud)

如果您给出了正确类型的更好示例以及一些示例数据,我可以提供更好的答案。


Emi*_*ary 2

您尚未指定您正在实现的模式(如果有),但正如另一个答案所提到的,您将必须在对象的构造过程中采用某种约定。不过,您不一定必须明确考虑每种类型...如果您对JSON数据的完整性感到满意,您也可能会有点懒惰地合并JSON数据$.extend

我还包括一个用于解析给定范围内的“类型”的辅助函数 - 这是项目中命名空间对象以避免污染全局范围的常见做法。例如:

function namespace(str, scope){
    scope = scope || window;
    var parts = str.split('.');
    while(parts.length) 
        scope = scope[parts.shift()];
    return scope;
}

Foo = {};
Foo.Bar = function(conf){
    // some kind of constructor
    $.extend(this, conf);
};
Run Code Online (Sandbox Code Playgroud)
// test...
var json = {
    type: 'Foo.Bar',
    var1: 1,
    var2: 2,
    var3: 3
};

var obj = new (namespace(json.type))(json);
console.log(obj, obj instanceof Foo.Bar);
Run Code Online (Sandbox Code Playgroud)

小提琴...或者适合您自己的代码:

$.getJSON("foo.json").done(function(data, textStatus, xhr){
    data.objects = $.map(data.objects, function(obj){
        return new (namespace(obj.type))(obj);
    });
});   
Run Code Online (Sandbox Code Playgroud)