在javascript中展平json数据结构

时间:2015-10-19 21:01:48

标签: javascript

我有一个json响应来自一个有点痛苦的服务。如何稍微展平此结构以便"not_restricted":{"doc_count": 976465}更改为"not_restricted":976465?我可以使用一个函数来检测所有类型的json文档中的这种结构并修改结果。

这是json的一般结构:

{
    "took": 159,
    "timed_out": false,
    "_shards": {
        "total": 6,
        "successful": 6,
        "failed": 0
    },
    "hits": {
        "total": 4909332,
        "max_score": 1,
        "hits": [
            {
                ...
            },
            {
                ...
            },
            {
                ...
            }
        ]
    },
    "aggregations": {
        "index_types": {
            "doc_count_error_upper_bound": 0,
            "sum_other_doc_count": 0,
            "buckets": [
                {
                    "key": "client",
                    "doc_count": 1958205,
                    "not_restricted": {
                        "doc_count": 976465
                    },
                    "restricted": {
                        "doc_count": 981740
                    }
                },
                {
                    "key": "ultimateparent",
                    "doc_count": 1616164,
                    "not_restricted": {
                        "doc_count": 741059
                    },
                    "restricted": {
                        "doc_count": 875105
                    }
                },
                {
                    "key": "facility",
                    "doc_count": 1334963,
                    "not_restricted": {
                        "doc_count": 914090
                    },
                    "restricted": {
                        "doc_count": 420872
                    }
                }
            ]
        }
    }
}

4 个答案:

答案 0 :(得分:5)

您可以使用reviver parameter of JSON.parse轻松完成此操作,它允许您过滤JSON中的每个对象:

var res = JSON.parse(json, function(k, o) {
    if (Object(o) !== o) return o; // primitive values
    var keys = Object.keys(o);
    if (keys.length == 1 && keys[0] == "doc_count")
        return o.doc_count;
    else
        return o;
});

如果您想确保仅在此类属性中替换k单身人士,您还可以测试"restricted"以包含doc_count左右。

答案 1 :(得分:1)

您可以使用LoDash让您的生活更轻松。包括它,然后你可以使用_.each

_.each(data.aggregations.index_types.buckets, function(n){
  n.not_restricted = n.not_restricted.doc_count;
  n.restricted = n.restricted.doc_count;
})

答案 2 :(得分:0)

如果你想通过对象并展平所有1个属性对象,你可以这样做:

for (var i = 0; i < data.aggregations["index_types"].buckets.length; i++) {
    var obj = data.aggregations["index_types"].buckets[i];
    for (var key in obj) {
        if (typeof obj[key] === "object" && Object.keys(obj[key]).length === 1) {
            //1 property object!
            obj[key] = obj[key][Object.keys(obj[key])[0]];
        } 
    }
}

演示:http://jsfiddle.net/jkm1vmbm/

答案 3 :(得分:0)

由于您说JSON实际上是字符串,如果您需要的只是特定的替换:

Replacing `{"doc_count": NUMBER}` with that `NUMBER`

你可以做的就是用正则表达式替换你想要的东西:

s.replace(/({"doc_count":([0-9]+)})/g, '$2')

其中的作用如下:

(                   // start capturing group 1
{\"doc_count\":     // match the string {\"doc_count\":
    (               // start capturing group 2
    [0-9]+          // match one or more digits
    )               // close capturing group 2
}                   // add the rest of the string (a closing bracket)  

然后,您可以在$2中使用replace()仅提取capturing group 2中的数字。

&#13;
&#13;
var json = {
  "aggregations": {
    "index_types": {
      "doc_count_error_upper_bound": 0,
      "sum_other_doc_count": 0,
      "buckets": [{
        "key": "client",
        "doc_count": 1958205,
        "not_restricted": {
          "doc_count": 976465
        },
        "restricted": {
          "doc_count": 981740
        }
      }, {
        "key": "ultimateparent",
        "doc_count": 1616164,
        "not_restricted": {
          "doc_count": 741059
        },
        "restricted": {
          "doc_count": 875105
        }
      }, {
        "key": "facility",
        "doc_count": 1334963,
        "not_restricted": {
          "doc_count": 914090
        },
        "restricted": {
          "doc_count": 420872
        }
      }]
    }
  }
};

var s = JSON.stringify(json);
// replace all instances of {doc_count: NUMBER} with that NUMBER
console.log(s.replace(/({"doc_count":([0-9]+)})/g, '$2'));
&#13;
&#13;
&#13;

我还注意到您在doc_countrestricted之外有属性non_restricted。如果您只想替换属性restrictednon_restricted中的属性,可以使用此正则表达式:

("((?:not_)?restricted"):{"doc_count":([0-9]+)})

在开头添加的部分基本上意味着&#34;从限制&#39;开始。选择&#39;不_&#39;在它之前&#34;

它的使用方式如下:

s.replace(/("((?:not_)?restricted"):{"doc_count":([0-9]+)})/g, '"$2:$3')

&#13;
&#13;
var json = {
  "aggregations": {
    "index_types": {
      "doc_count_error_upper_bound": 0,
      "sum_other_doc_count": 0,
      "buckets": [{
        "key": "client",
        "doc_count": 1958205,
        "not_restricted": {
          "doc_count": 976465
        },
        "restricted": {
          "doc_count": 981740
        }
      }, {
        "key": "ultimateparent",
        "doc_count": 1616164,
        "not_restricted": {
          "doc_count": 741059
        },
        "restricted": {
          "doc_count": 875105
        }
      }, {
        "key": "facility",
        "doc_count": 1334963,
        "not_restricted": {
          "doc_count": 914090
        },
        "restricted": {
          "doc_count": 420872
        }
      }]
    }
  }
};

var s = JSON.stringify(json);
console.log(s.replace(/("((?:not_)?restricted"):{"doc_count":([0-9]+)})/g, '"$2:$3'));
&#13;
&#13;
&#13;

注意:对?:使用(?:not_)会使括号中的部分成为非捕获组,因此它不会在捕获组中计算。术语&#34;限制&#34;使用可选的&#34;而不是_&#34;在它现在包含在第2组中之前,数字值在第3组中。我们还需要预先设置"并将这两个组合并为: