【问题标题】:converting JSON object ot array of JSON objects on basis of key - Code in Python根据键将 JSON 对象转换为 JSON 对象数组 - Python 中的代码
【发布时间】:2019-01-05 17:36:36
【问题描述】:

我有一个 JSON 对象数组。示例数组如下:

[
  {
    "evt.category": "file",
    "evt.cpu": 0,
    "evt.num": 10078507,
    "evt.res": "SUCCESS",
    "evt.time": 1532841047277584400,
    "evt.type": "read",
    "fd.filename": "libnss_files.so.2",
    "fd.name": "/lib/x86_64-linux-gnu/libnss_files.so.2",
    "fd.num": 13,
    "fd.type": "file",
    "fd.uid": "1996913",
    "proc.loginshellid": 19968,
    "proc.name": "last",
    "proc.pid": 19969,
    "thread.ismain": true,
    "thread.tid": 19969
  },
  {
    "evt.buffer": "1000",
    "evt.category": "file",
    "evt.cpu": 0,
    "evt.num": 10078564,
    "evt.res": "SUCCESS",
    "evt.time": 1532841047277731300,
    "evt.type": "read",
    "fd.filename": "loginuid",
    "fd.name": "/proc/16009/loginuid",
    "fd.num": 13,
    "fd.type": "file",
    "fd.uid": "1996913",
    "proc.loginshellid": 19968,
    "proc.name": "last",
    "proc.pid": 19969,
    "thread.ismain": true,
    "thread.tid": 19969
  },
  {
    "evt.buffer": "",
    "evt.category": "file",
    "evt.cpu": 0,
    "evt.num": 10078566,
    "evt.res": "SUCCESS",
    "evt.time": 1532841047277733400,
    "evt.type": "read",
    "fd.filename": "loginuid",
    "fd.name": "/proc/16009/loginuid",
    "fd.num": 13,
    "fd.type": "file",
    "fd.uid": "1996913",
    "proc.loginshellid": 19968,
    "proc.name": "last",
    "proc.pid": 19969,
    "thread.ismain": true,
    "thread.tid": 19969
  }
]

我想重新构造这个数组,以便将每个对象转换为另一个数组,并且每个数组都应该包含基于这些键的 JSON 对象,例如 evtproc thread 等的 JSON 对象。

我尝试了一些在线网站来做到这一点,但都不起作用。

请帮忙。

编辑: 我想要的输出如下:

[
  {
    "evt": {
      "category": "file",
      "cpu": 0,
      "num": 10078507,
      "res": "SUCCESS",
      "time": 1532841047277584400,
      "type": "read"
    },
    "fd": {
      "filename": "libnss_files.so.2",
      "name": "/lib/x86_64-linux-gnu/libnss_files.so.2",
      "num": 13,
      "type": "file",
      "uid": "1996913"
    },
    "proc": {
      "loginshellid": 19968,
      "name": "last",
      "pid": 19969
    },
    "thread": {
      "ismain": true,
      "tid": 19969
    }
  },
  {
    "evt": {
      "buffer": "1000",
    "category": "file",
    "cpu": 0,
    "num": 10078564,
    "res": "SUCCESS",
    "time": 1532841047277731300,
    "type": "read"
    },
    "fd": {
    "filename": "loginuid",
    "name": "/proc/16009/loginuid",
    "num": 13,
    "type": "file",
    "uid": "1996913"
    },
    "proc": {
      "loginshellid": 19968,
    "name": "last",
    "pid": 19969
    },
    "thread" : {
    "ismain": true,
    "tid": 19969
    }
  }
]

【问题讨论】:

  • 能否为您的期望输出添加示例?
  • @DavidWinder 我现在已将其添加到问题中。希望现在我的问题更清楚了。谢谢。
  • @cstayyab,你想用哪种编程语言来做这个转换?
  • @BráulioFigueiredo ,我没有提到具体的编程语言,因为在我看来可能有一种通用的方法(例如循环)。但具体来说,最好是在python 3
  • @cstayyab 不幸的是我不懂 python,但我用 Javascript 解决了你的问题。如果有帮助,请查看我的回答

标签: python arrays json


【解决方案1】:
import json

list_of_objects = json.loads(json_string)

new_list = []
for complex_object in list_of_objects:
    new_object = {}
    for composite_key, value in complex_object.items():
        key, subkey = composite_key.split(".")
        if key not in new_object:
            new_object[key] = {}
        new_object[key][subkey] = value
    new_list.append(new_object)

json_string = json.dumps(new_list)

【讨论】:

    【解决方案2】:

    var obj = [{
            "evt.category": "file",
            "evt.cpu": 0,
            "evt.num": 10078507,
            "evt.res": "SUCCESS",
            "evt.time": 1532841047277584400,
            "evt.type": "read",
            "fd.filename": "libnss_files.so.2",
            "fd.name": "/lib/x86_64-linux-gnu/libnss_files.so.2",
            "fd.num": 13,
            "fd.type": "file",
            "fd.uid": "1996913",
            "proc.loginshellid": 19968,
            "proc.name": "last",
            "proc.pid": 19969,
            "thread.ismain": true,
            "thread.tid": 19969
        },
        {
            "evt.buffer": "1000",
            "evt.category": "file",
            "evt.cpu": 0,
            "evt.num": 10078564,
            "evt.res": "SUCCESS",
            "evt.time": 1532841047277731300,
            "evt.type": "read",
            "fd.filename": "loginuid",
            "fd.name": "/proc/16009/loginuid",
            "fd.num": 13,
            "fd.type": "file",
            "fd.uid": "1996913",
            "proc.loginshellid": 19968,
            "proc.name": "last",
            "proc.pid": 19969,
            "thread.ismain": true,
            "thread.tid": 19969
        },
        {
            "evt.buffer": "",
            "evt.category": "file",
            "evt.cpu": 0,
            "evt.num": 10078566,
            "evt.res": "SUCCESS",
            "evt.time": 1532841047277733400,
            "evt.type": "read",
            "fd.filename": "loginuid",
            "fd.name": "/proc/16009/loginuid",
            "fd.num": 13,
            "fd.type": "file",
            "fd.uid": "1996913",
            "proc.loginshellid": 19968,
            "proc.name": "last",
            "proc.pid": 19969,
            "thread.ismain": true,
            "thread.tid": 19969
        }
    ];
    
    function convertObj(obj) {
        var resultArray = [];
        obj.forEach(item => {
            var resultObj = {};
            for (var property in item) {
                var array = property.split('.');
                var reference = resultObj;
                for (var i = 0; i < array.length-1; i++) {
                    if (!reference[array[i]]){
                        reference[array[i]] = {};
                    }
                    reference = reference[array[i]];
                }
                reference[array[array.length-1]] = item[property];
            }
            resultArray.push(resultObj);
        });
        return resultArray;
    }
    
    console.log(convertObj(obj));

    【讨论】:

    • 它没有提供所需的输出。它只显示每个对象中的第一个子键值。
    • 是真的...已修复:)
    【解决方案3】:

    使用 可以轻松完成任务,例如使用 jq 可执行文件、python jq 模块或 python pyjq 模块。

    无论您选择哪种模式,合适的过滤器应该是:

    def restructure:
      def splitup: index(".") as $ix | [ .[0:$ix], .[1+$ix:] ];
      to_entries
      | map( (.key|splitup) + [.value] )
      | reduce .[] as $x ({}; .[$x[0]][$x[1]] = $x[2]) ;
    
    map(restructure)
    

    示例(使用 jq 可执行文件)

    使用示例输入,调用:

    jq -f program.jq input.jq
    

    产量:

    [
      {
        "evt": {
          "category": "file",
          "cpu": 0,
          "num": 10078507,
          "res": "SUCCESS",
          "time": 1532841047277584400,
          "type": "read"
        },
        "fd": {
          "num": 13,
          "name": "/lib/x86_64-linux-gnu/libnss_files.so.2",
          "filename": "libnss_files.so.2",
          "type": "file",
          "uid": "1996913"
        },
        "proc": {
          "loginshellid": 19968,
          "name": "last",
          "pid": 19969
        },
        "thread": {
          "ismain": true,
          "tid": 19969
        }
      },
      {
        "evt": {
          "buffer": "1000",
          "category": "file",
          "cpu": 0,
          "num": 10078564,
          "res": "SUCCESS",
          "time": 1532841047277731300,
          "type": "read"
        },
        "fd": {
          "name": "/proc/16009/loginuid",
          "filename": "loginuid",
          "num": 13,
          "type": "file",
          "uid": "1996913"
        },
        "proc": {
          "loginshellid": 19968,
          "name": "last",
          "pid": 19969
        },
        "thread": {
          "ismain": true,
          "tid": 19969
        }
      },
      {
        "evt": {
          "buffer": "",
          "category": "file",
          "cpu": 0,
          "num": 10078566,
          "res": "SUCCESS",
          "time": 1532841047277733400,
          "type": "read"
        },
        "fd": {
          "name": "/proc/16009/loginuid",
          "filename": "loginuid",
          "num": 13,
          "type": "file",
          "uid": "1996913"
        },
        "proc": {
          "loginshellid": 19968,
          "name": "last",
          "pid": 19969
        },
        "thread": {
          "ismain": true,
          "tid": 19969
        }
      }
    ]
    

    鲁棒化

    以上假设所有键名都至少有一个“.”。如果不能假设,那么可以使用restructure 的以下变体:

    def restructure:
      def splitup: index(".") as $ix
        | if $ix then [ .[0:$ix], .[1+$ix:] ]
          else [ ., null] 
          end;
      to_entries
      | map( (.key|splitup) + [.value] )
      | reduce .[] as $x ({};
          if $x[1] == null then .[$x[0]] = $x[2]
          else .[$x[0]][$x[1]] = $x[2]
          end ) ;
    

    【讨论】:

      【解决方案4】:

      我不知道python,但这是你可以用JS做到的

      const arr = [
        {
          "evt.category": "file",
          "evt.cpu": 0,
          "evt.num": 10078507,
          "evt.res": "SUCCESS",
          "evt.time": 1532841047277584400,
          "evt.type": "read",
          "fd.filename": "libnss_files.so.2",
          "fd.name": "/lib/x86_64-linux-gnu/libnss_files.so.2",
          "fd.num": 13,
          "fd.type": "file",
          "fd.uid": "1996913",
          "proc.loginshellid": 19968,
          "proc.name": "last",
          "proc.pid": 19969,
          "thread.ismain": true,
          "thread.tid": 19969
        },
        {
          "evt.buffer": "1000",
          "evt.category": "file",
          "evt.cpu": 0,
          "evt.num": 10078564,
          "evt.res": "SUCCESS",
          "evt.time": 1532841047277731300,
          "evt.type": "read",
          "fd.filename": "loginuid",
          "fd.name": "/proc/16009/loginuid",
          "fd.num": 13,
          "fd.type": "file",
          "fd.uid": "1996913",
          "proc.loginshellid": 19968,
          "proc.name": "last",
          "proc.pid": 19969,
          "thread.ismain": true,
          "thread.tid": 19969
        },
        {
          "evt.buffer": "",
          "evt.category": "file",
          "evt.cpu": 0,
          "evt.num": 10078566,
          "evt.res": "SUCCESS",
          "evt.time": 1532841047277733400,
          "evt.type": "read",
          "fd.filename": "loginuid",
          "fd.name": "/proc/16009/loginuid",
          "fd.num": 13,
          "fd.type": "file",
          "fd.uid": "1996913",
          "proc.loginshellid": 19968,
          "proc.name": "last",
          "proc.pid": 19969,
          "thread.ismain": true,
          "thread.tid": 19969
        }
      ]
      
      
      const newArr = arr.map(obj =>{
        
          const newObj = {};
      
          for(let key in obj){
            const [mainKey,subKey] =  key.split('.')
            if(newObj[mainKey] === undefined){
              newObj[mainKey] = {}
            } 
             newObj[mainKey][subKey] = obj[key];
          }
          
          return newObj
          
          
      })
      
      console.log(newArr)

      【讨论】:

      • 我喜欢你做这件事的方式,但我正在将程序 (Sysdig) 的输出传递给我的程序,遗憾的是,sysdig 无法调用 JS 文件。此外,我还必须在转换后做更多我在 JS 中做不到的事情。
      猜你喜欢
      • 2018-10-11
      • 2014-05-26
      • 2012-07-21
      • 2020-10-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-18
      相关资源
      最近更新 更多