【问题标题】:Any standard JavaScript library for transforming JS objects任何用于转换 JS 对象的标准 JavaScript 库
【发布时间】:2013-08-09 19:35:13
【问题描述】:

我有一个复杂的嵌套 JavaScript 对象。要求是完全展平对象或仅展平其中的一些成员。

var obj = {
     a: {
        b: {
          c: {
            d: "Varun"   
          },
          e: "kumar"
        }
    }   
};

预期的结果对象:

{d: "Varun", e: "kumar"} 

我编写了一个简单的转换实用程序,它将接受 {"a.b.c.d": "d"} 形式的访问器映射并将对象转换为新对象。我暂时不支持数组。此外,转换实用程序只能将复杂对象简化为更简单对象,反之亦然(即从简单成员构造新成员对象)。

"use strict";
var ObjectUtil = (function () {
    // constructor
    var cls = function () {

    };

    // public static
    cls.getValueFromAccessor = function (obj, accessor) {
        if (obj == null || accessor == null)
            return null;

        return accessor.split(".").reduce(function(prev, current, index) {
            var reducedObject = prev;
            if (index == 1)
                reducedObject = obj[prev];

            if (reducedObject == null)
                return null;

            return reducedObject[current];
        });
    };

    cls.transform = function(obj, accessorMap, overlay) {
        var result;

        if (overlay)
            result = obj;
        else
            result = {};

        for (var k in accessorMap) {
            result[accessorMap[k]] = cls.getValueFromAccessor(obj, k);
        }

        return result;
    };

    return cls;
})();

var obj = {
     a: {
        b: {
          c: {
            d: "Varun"   
          },
          e: "kumar"
        }
    }   
};

var accessorMap = {
    "a.b.c.d": "d",
    "a.b.e": "e"
}

ObjectUtil.getValueFromAccessor(obj, "a.b.c.d");
console.log(ObjectUtil.transform(obj, accessorMap, false));
console.log(ObjectUtil.transform(obj, accessorMap, true));

是否有将对象从一种形式转换为另一种形式的标准方法。有没有可用的库?

【问题讨论】:

  • There is no such thing as a "JSON object"。您的问题与 JSON没有任何关系。而且 JavaScript 没有标准库。
  • 是的,我明白这一点。我不喜欢互换使用它们。
  • underscore.js 是一个广泛使用的库,用于执行此类操作。提取特定属性、展平集合、map/reduce 等。

标签: javascript javascript-framework


【解决方案1】:
var converter = new (function(){
    var divider = ".";
    var doFlatten = function(source, path, newObj){
        for(var i in source){
            if(source.hasOwnProperty(i)){
                var tempPath = (path == "") ? i : path + divider + i;
                if(typeof source[i] == "object"){
                    doFlatten(source[i], tempPath, newObj);
                }
                else{
                    newObj[tempPath] = source[i];
                }
            }
        }
    };
    this.flatten = function(source){
        if(typeof source == "object"){
            var newObj = {};
            doFlatten(source, "", newObj);
            return newObj;
        }
        return source;
    };
    this.expand = function(source){
        var dest = {};
        if(typeof source == "object"){
            for(var i in source){
                if(source.hasOwnProperty(i)){
                    var path = i.split(divider);
                    var temp = dest;
                    var prevTemp = dest;
                    for(var j in path){
                        if(!temp.hasOwnProperty(path[j])){
                            temp[path[j]] = {};
                        }
                        prevTemp = temp;
                        temp = temp[path[j]];
                    }
                    prevTemp[path[path.length - 1]] = source[i];
                }
            }
            return dest;
        }
        return source;
    };
});

用法:

var flatObj = converter.flatten({
    a: {
        b: {
            c: {
                d: "Varun"   
            },
            e: "kumar"
        }
    }   
});
console.log(flatObj);
// {"a.b.c.d": "Varun", "a.b.e": "kumar"}

var expanded = converter.expand(flatObj);
console.log(expanded);
// {
//    a: {
//        b: {
//            c: {
//                d: "Varun"   
//            },
//            e: "kumar"
//        }
//    }   
// }

【讨论】:

    【解决方案2】:

    看看js-api-smith,它以声明的方式提供了 JavaScript 对象的转换。它可以安装为NPM package,如果你在浏览器中使用它可以使用browserify

    这是一个解决问题的示例:

    const apiSmith = require('js-api-smith');
    
    // one way
    const transformations1 = {
      d: "a.b.c.d",
      // d: ["a", "b", "c", "d"],   // can also be written this way
      e: "a.b.e"
    };
    
    const from1 = {
      a: {
        b: {
          c: {
            d: "Varun"
          },
          e: "kumar"
        }
      }
    };
    
    const transformed1 = apiSmith.smash(transformations1, from1);
    // -> { d: "Varun", e: "kumar" }
    
    // or the other way
    const transformations2 = {
      "a.b.c.d": "d",
      "a.b.e": "e"
    };
    
    const from2 = { d: "Varun", e: "kumar" };
    
    const transformed2 = apiSmith.smash(transformations2, from2);
    // -> {
    //   a: {
    //     b: {
    //       c: {
    //         d: "Varun"
    //       },
    //       e: "kumar"
    //     }
    //   }
    // };

    该库还支持设置默认值和指定属性的转换函数,有兴趣的可以查看the documentations

    希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多