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



我有一个非常复杂的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"
}

您需要一个递归搜索函数。

以下ES6代码段递归遍历obj中的所有节点,直到找到

它不认为包含数组的节点是用"子段"标识的。但是您可以执行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'))

如果您只查找数组的第一个元素,那么您可以尝试。

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));

这里有一种可能性,使用给定的关键字首先搜索深度,如果找不到,则返回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'),然后简单地将该函数应用于您的数据。

但请注意,如果您的数据过于不一致,任何像这样规范化数据的尝试都可能会出现问题。如果您能够提前驯服它,那么您的代码的其余部分可能会更简单。

相关内容

最新更新