NodeJS 如何评估JSON键以匹配特定键并提取该键的值?

sqyvllje  于 2023-06-22  发布在  Node.js
关注(0)|答案(3)|浏览(139)

我有一个非常复杂的JSON结构,其中嵌套了JSON和数组。我想从中获取一个包含关键元数据的对象(json)。JSON的顺序不是每次都固定的。我如何为那个JSON获取值?这是JSON结构示例

{
"id": "*******",
"name": "createNewApiKey",
"start_time": 1543504061.474,
"end_time": 1543504062.059,
"parent_id": "******",
"aws": {
    "function_arn": "********",
    "resource_names": [
        "****"
    ],
    "account_id": "******"
},
"trace_id": "1-5c0000bc-*****",
"origin": "AWS::Lambda::Function",
"subsegments": [
    {
        "id": "5d680f995ca8cfd9",
        "name": "*******",
        "start_time": 1543504061.503,
        "end_time": 1543504061.977,
        "fault": true,
        "error": true,
        "cause": {
            "exceptions": [
                {
                    "stack": [
                        {
                            "path": "/var/task/node_modules/aws-xray-sdk-core/lib/patchers/aws_p.js",
                            "line": 77,
                            "label": "captureAWSRequest [as customRequestHandler]"
                        },
                        {
                            "path": "/var/runtime/node_modules/aws-sdk/lib/service.js",
                            "line": 267,
                            "label": "addAllRequestListeners"
                        },
                        {
                            "path": "/var/runtime/node_modules/aws-sdk/lib/service.js",
                            "line": 191,
                            "label": "makeRequest"
                        },
                        {
                            "path": "/var/runtime/node_modules/aws-sdk/lib/service.js",
                            "line": 499,
                            "label": "svc.anonymous function [as getSecretValue]"
                        },
                        {
                            "path": "/var/task/index.js",
                            "line": 34,
                            "label": "exports.handler"
                        }
                    ],
                    "message": "*****",
                    "type": "ResourceNotFoundException",
                    "remote": true
                }
            ],
            "working_directory": "/var/task"
        },
        "http": {
            "response": {
                "status": 400
            }
        },
        "aws": {
            "operation": "GetSecretValue",
            "region": "eu-west-1",
            "request_id": "******",
            "retries": 0
        },
        "namespace": "aws",
        "subsegments": [
            {
                "id": "*****",
                "name": "Metadata",
                "start_time": 1543504061.981,
                "end_time": 1543504062.017,
                "metadata": {
                    "default": {
                        "inputData": {
                            "clientName": "a",
                            "productOwner": "dev"
                        },
                        "response": "Wrong client ID"
                    }
                }
            }
        ]
    },
    {
        "id": "********",
        "name": "Initialization",
        "start_time": 1543504060.726,
        "end_time": 1543504061.47,
        "aws": {
            "*****"
        }
    },
    {
        "id": "********",
        "name": "annotations",
        "start_time": 1543504061.477,
        "end_time": 1543504061.478,
        "annotations": {
            "User": "dev",
            "Name": "a"
        }
    }
]

}

**可以包含JSON或数组

这里我想在JSON下面取

{
                          "inputData": {
                            "id": "*****",
                            "givenClientName": "abc1012",
                            "productOwner": "dev"
                          },
                          "response": "** successfully"
                        }
nuypyhwy

nuypyhwy1#

你需要一个递归搜索函数。
下面的ES6代码段递归遍历***obj***中的所有节点,直到找到***key***。
它不假设包含数组的节点用“子段”标识。但是您可以执行k == 'subsegments' && Array.isArray(obj[k])来强制执行此规则。

function search(obj, key) {
  let res = null;

  (function searchNode(obj) {
    Object.keys(obj).some(k => {
      if(k == key) {
        res = obj[k];
        return true;
      }
      return Array.isArray(obj[k]) && obj[k].some(searchNode);
    })
  })(obj);

  return res;
}

obj = {
  "id": "*******",
  "name": "createNewApiKey",
  "start_time": 1543504061.474,
  "end_time": 1543504062.059,
  "parent_id": "******",
  "subsegments": [
    {
      "subsegments": [
        {
          "subsegments": [
            {
              "subsegments": [
                {
                  "metadata": {
                    "default": {
                      "inputData": {
                        "id": "*****",
                        "givenClientName": "abc1012",
                        "productOwner": "dev"
                      },
                      "response": "** successfully"
                    }
                  }
                }
              ]
            }
          ]
        }
      ]
    }
  ]
};

console.log(search(obj, 'metadata'))
pbossiut

pbossiut2#

如果你只想找数组的第一个元素,那么你可以试试。

var a = {
    "subsegments": [{
        "subsegments": [{
            "subsegments": [{
                "subsegments": [{
                    "metadata": {
                        "default": {
                            "inputData": {
                                "id": "",
                                "givenClientName": "abc1012",
                                "productOwner": "dev"
                            },
                            "response": " successfully"
                        }
                    }
                }]
            }]
        }, {
            "subsegments": [{
                "subsegments": [{
                    "metadata": {
                        "default": {
                            "inputData": {
                                "id": "",
                                "givenClientName": "abc1012",
                                "productOwner": "dev"
                            },
                            "response": " successfully"
                        }
                    }
                }]
            }]
        }]
    }]
}

function test(params) {
    if (!params) {
        return null;
    }
    if (params.default) {
        return params.default;
    } else if (Array.isArray(params)) {
        var subsegments = params[0].subsegments || params[0].metadata;
        return test(subsegments);
    } else {
        return test(params.subsegments);
    }
}

console.log(test(a));
u1ehiz5o

u1ehiz5o3#

这里有一种可能性,使用给定的键搜索深度优先的项目,如果没有找到,则返回null

const findFirstKey = (name) => (obj)  => !(obj instanceof Object)
  ? null
  : name in obj
    ? obj[name]
    : Object.keys(obj).reduce((res, key) => res || findFirstKey(name)(obj[key]), null)

const response = {"aws": {"account_id": "******", "function_arn": "********", "resource_names": ["****"]}, "end_time": 1543504062.059, "id": "*******", "name": "createNewApiKey", "origin": "AWS::Lambda::Function", "parent_id": "******", "start_time": 1543504061.474, "subsegments": [{"aws": {"operation": "GetSecretValue", "region": "eu-west-1", "request_id": "******", "retries": 0}, "cause": {"exceptions": [{"message": "*****", "remote": true, "stack": [{"label": "captureAWSRequest [as customRequestHandler]", "line": 77, "path": "/var/task/node_modules/aws-xray-sdk-core/lib/patchers/aws_p.js"}, {"label": "addAllRequestListeners", "line": 267, "path": "/var/runtime/node_modules/aws-sdk/lib/service.js"}, {"label": "makeRequest", "line": 191, "path": "/var/runtime/node_modules/aws-sdk/lib/service.js"}, {"label": "svc.anonymous function [as getSecretValue]", "line": 499, "path": "/var/runtime/node_modules/aws-sdk/lib/service.js"}, {"label": "exports.handler", "line": 34, "path": "/var/task/index.js"}], "type": "ResourceNotFoundException"}], "working_directory": "/var/task"}, "end_time": 1543504061.977, "error": true, "fault": true, "http": {"response": {"status": 400}}, "id": "5d680f995ca8cfd9", "name": "*******", "namespace": "aws", "start_time": 1543504061.503, "subsegments": [{"end_time": 1543504062.017, "id": "*****", "metadata": {"default": {"inputData": {"clientName": "a", "productOwner": "dev"}, "response": "Wrong client ID"}}, "name": "Metadata", "start_time": 1543504061.981}]}, {"aws": {"*****": "blah"}, "end_time": 1543504061.47, "id": "********", "name": "Initialization", "start_time": 1543504060.726}, {"annotations": {"Name": "a", "User": "dev"}, "end_time": 1543504061.478, "id": "********", "name": "annotations", "start_time": 1543504061.477}], "trace_id": "1-5c0000bc-*****"}

const meta = findFirstKey('metadata')(response)

console.log(meta)

在这里,您还可以编写const getMeta = findFirstKey('metadata'),然后简单地将该函数应用于您的数据。
但请注意,如果您的数据太不一致,任何像这样将其规范化的尝试最终都会出现问题。如果你能在前面驯服它,你的代码的其余部分可能会更简单。

相关问题