【问题标题】:Parse string of file path to json object将文件路径字符串解析为 json 对象
【发布时间】:2018-04-07 05:30:26
【问题描述】:

我有如下 URL 列表。如何将其转换为完整的 json 对象?

我的 URL 数组。

[
"path1/subpath1/file1.doc","path1/subpath1/file2.doc","path1/subpath2/file1.doc","path1/subpath2/file2.doc","path2/subpath1/file1.doc","path2/subpath1/file2.doc","path2/subpath2/file1.doc","path2/subpath2/file2.doc","path2/subpath2/additionalpath1/file1.doc"
]

我希望这是一个 json 对象,例如:

{
   "path1":{
      "subpath1":["file1.doc","file2.doc"],
      "subpath2":["file1.doc","file2.doc"]
   },
   "path2":{
      "subpath1":["file1.doc","file2.doc"],
      "subpath2":["file1.doc","file2.doc"],
      "additionalpath1":{
          "additionalpath1":["file1.doc"]
      }
   }
}

如何做到这一点?

我用下面的代码 sn-ps 试过了。但是缺少几个文件夹对象。

如果您尝试此代码,您会发现缺少test1 和其他objects

<html>
  <script src="https://code.jquery.com/jquery-1.10.2.js"></script>
<body>


<p id="demo"></p>

<script>
let paths = [ "admin/640954.jpg", "admin/test1/3m-nd.jpg", 
"admin/test1/Acct.png", "admin/test1/additional/111.gif", "admin/test1/additional/Aard.jpg", 
"dp/151292.jpg", "dp/151269.jpg", "dp/1515991.jpg" ];


function getMap(urls){
    var map = {};
    urls.forEach(function(url){
        var parts = url.split("/");
        makePath(map, parts);
    })
    return map;
}

function makePath(map,parts){
    var currentPath = map;
    for(var i = 0 ; i < parts.length - 1 ; i++ ){
            if(i == parts.length -2 ){
                currentPath[parts[i]]  = currentPath[parts[i]] || [];
                currentPath[parts[i]].push(parts[++i]);
            }else{
                currentPath[parts[i]] =  currentPath[parts[i]] || {};
                currentPath = currentPath[parts[i]];
            }
    }

}

document.getElementById("demo").innerHTML=JSON.stringify(getMap(paths));
</script>

</body>
</html>

【问题讨论】:

  • 您可以使用递归映射算法来做到这一点。
  • 您使用哪种语言编写代码?
  • @MohitMutha 看看标签。
  • 你可以在最后一个正斜杠之后抓取所有内容。你已经尝试过什么?

标签: javascript jquery json


【解决方案1】:

您可以使用.split("/") 并迭代结果,在嵌套对象中创建属性:

let paths = [
  "path1/subpath1/file111.doc",
  "path1/subpath1/file112.doc",
  "path1/subpath2/file121.doc",
  "path1/subpath2/file122.doc",
  "path2/subpath1/file211.doc",
  "path2/subpath1/file212.doc",
  "path2/subpath2/file221.doc",
  "path2/subpath2/file222.doc",
  "path2/additionalpath3/additionalpath1/file2311.doc"
];

let treePath = {};
paths.forEach(path => {
  let levels = path.split("/");
  let file = levels.pop();

  let prevLevel = treePath;
  let prevProp = levels.shift();

  levels.forEach(prop => {
    prevLevel[prevProp] = prevLevel[prevProp] || {};
    prevLevel = prevLevel[prevProp];
    prevProp = prop;
  });

  prevLevel[prevProp] = (prevLevel[prevProp] || []).concat([file]);
});

console.log(treePath);

或者:

let paths = [
  "path1/subpath1/file111.doc",
  "path1/subpath1/file112.doc",
  "path1/subpath2/file121.doc",
  "path1/subpath2/file122.doc",
  "path2/subpath1/file211.doc",
  "path2/subpath1/file212.doc",
  "path2/subpath2/file221.doc",
  "path2/subpath2/file222.doc",
  "path2/additionalpath3/additionalpath1/file2311.doc"
];

let treePath = {};
paths.forEach(path => {
  let levels = path.split("/");
  let file = levels.pop();

  levels.reduce((prev, lvl, i) => {
    return prev[lvl] = (levels.length - i - 1) ? prev[lvl] || {} : (prev[lvl] || []).concat([file]);
  }, treePath);
});

console.log(treePath);

【讨论】:

  • 如果我使用下面的字符串,则 test1 对象丢失。 let paths = [ "admin/640954_15681069_2837056_82dea68d_image.jpg", "admin/test1/3m-adjustable-notebook-riser-laptop-stand-740x740.jpg", "admin/test1/Acct-Mgmt-Templates-1024x611.png", "admin/test1/additional/111.gif", "admin/test1/additional/Adminto-Admin-Dashboard.jpg", "dp/1512966420652.jpg", "dp/1512966492869.jpg", "dp/1515556524991.jpg" ];
  • 预期结果是什么?
  • 老兄。预期的结果是,文件名应该是字符串数组。文件夹名称应该是对象名称。我正在从服务器端接收字符串列表。我必须将字符串更改为文件夹视图,如树视图。所有文件夹名称都应该是父 li 和 .doc、.jpg 文件将是最少的子。
  • 老兄。你的规范是模棱两可的。老兄。这就是为什么我问结果是什么。老兄。这就是为什么没有人能见到他们,因为他们没有意义。老兄。 test1 文件夹包含子文件夹和文件。老兄。当一个文件夹有子文件夹时,它就是一个对象。老兄。当一个文件夹有文件时,它就是一个数组。老兄。如果它同时有文件和子文件夹,它会是什么?老兄。有些东西不能同时是一个对象和一个数组。老兄。
  • :)。那怎么实现呢?我只想在树视图中显示文件夹列表。当他们点击相应的文件夹时,我会显示里面的对象。
【解决方案2】:

我已经为你制作了一半代码。检查它是否对您有帮助。

您可以使用它并进行一些更改以实现您的目标。

<!DOCTYPE html>
<html>
  <script src="https://code.jquery.com/jquery-1.10.2.js"></script>
<body>

<p>Click the button to display the array values after the split.</p>

<button onclick="myFunction()">Try it</button>

<p id="demo"></p>

<script>
function myFunction() {
    var str = '"path1/subpath1/file1.doc","path1/subpath1/file2.doc","path1/subpath2/file1.doc","path1/subpath2/file2.doc","path2/subpath1/file1.doc","path2/subpath1/file2.doc","path2/subpath2/file1.doc","path2/subpath2/file2.doc","path2/subpath2/additionalpath1/file1.doc"';
    var res = str.split(",");
    document.getElementById("demo").innerHTML = res[0];

    var finalresult = [];
    var innerarray = [];
    var outer = [];
    var outer1 = [];
    var inner =[];
    jQuery.each( res, function( i, val ) {
      res1 = val.split("/");
      jQuery.each( res1, function( i2, val1 ) 
      {
            if(i2 == 0 && !(outer.includes(val1)))
            {
                outer.push(val1);
            }
            else if(i2 == 1 && !(outer1.includes(val1)))
            {
                outer1.push(val1);
            }
            else if(!(inner.includes(val1)))
            {
                inner.push(val1);
            }
        console.log(outer);
      });

    });

}
</script>

</body>
</html>

【讨论】:

    【解决方案3】:
    function filePathOject (arr) {
      const ret = {};
      arr.forEach((path) => {
        const dirs = path.split('/');
        const filename = dirs.pop();
    
        let dirObject = ret;
        dirs.forEach((dir, i) => {
          if (i === dirs.length - 1) {
            dirObject[dir] = dirObject[dir] || [];
            dirObject[dir].push(filename);
          } else {
            dirObject[dir] = dirObject[dir] || {};
          }
          dirObject = dirObject[dir];
        });
      });
    
      return ret;
    }
    

    【讨论】:

    • 如果我使用下面的字符串,则 test1 对象丢失。 let paths = [ "admin/640954_15681069_2837056_82dea68d_image.jpg", "admin/test1/3m-adjustable-notebook-riser-laptop-stand-740x740.jpg", "admin/test1/Acct-Mgmt-Templates-1024x611.png", "admin/test1/additional/111.gif", "admin/test1/additional/Adminto-Admin-Dashboard.jpg", "dp/1512966420652.jpg", "dp/1512966492869.jpg", "dp/1515556524991.jpg" ];
    【解决方案4】:

    你可以这样做。

    var urls = [
    "path1/subpath1/file1.doc","path1/subpath1/file2.doc","path1/subpath2/file1.doc","path1/subpath2/file2.doc","path2/subpath1/file1.doc","path2/subpath1/file2.doc","path2/subpath2/file1.doc","path2/subpath2/file2.doc","path2/subpath2/additionalpath1/file1.doc"
    ]
    
    function getMap(urls){
    var map = {};
    
    urls.forEach(function(url){
        var parts = url.split("/");
        makePath(map, parts);
    })
    return map;
    }
    
    function makePath(map,parts){
        var currentPath = map;
        for(var i = 0 ; i < parts.length - 1 ; i++ ){
                if(i == parts.length -2 ){
                    currentPath[parts[i]]  = currentPath[parts[i]] || [];
                    currentPath[parts[i]].push(parts[++i]);
                }else{
                    currentPath[parts[i]] =  currentPath[parts[i]] || {};
                    currentPath = currentPath[parts[i]];
                }
        }
    
    }
    getMap()
    

    给你留下一个部分:)

    【讨论】:

    • 如果我使用下面的字符串,则 test1 对象丢失。 let paths = [ "admin/640954_15681069_2837056_82dea68d_image.jpg", "admin/test1/3m-adjustable-notebook-riser-laptop-stand-740x740.jpg", "admin/test1/Acct-Mgmt-Templates-1024x611.png", "admin/test1/additional/111.gif", "admin/test1/additional/Adminto-Admin-Dashboard.jpg", "dp/1512966420652.jpg", "dp/1512966492869.jpg", "dp/1515556524991.jpg" ];
    • 我没有看到这个代码的错误。你能详细说明一下吗?
    • 我在问题部分添加了html。我得到了 {"admin":["640954.jpg"],"dp":["151292.jpg","151269.jpg","1515991.jpg"]} 和 test1 和 additional 对象的结果。
    【解决方案5】:

    也许您也希望在数组中包含子目录

    
    const path = '/home/user/dir/file';
    var next;
    
    path.split('/').reverse().forEach(name => {
      if (name === "") return;
      if (typeof(next) === 'undefined') {
        next = [String(name)];
      } else {
        var current = {};
        current[name] = next;
        next = [current];
      }
    });
    console.log(JSON.stringify(next));
    // [{"home":[{"user":[{"dir":["file"]}]}]}]
    
    

    然后可以连接对象

    【讨论】:

      猜你喜欢
      • 2020-05-18
      • 2013-03-12
      • 1970-01-01
      • 2019-07-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-14
      • 1970-01-01
      相关资源
      最近更新 更多