I have the nested json object in the snippet below and want to find all occurrences of '$schema' and save the whole object that contains that schema value into another object. I tried using lodash filter but, was unsuccessful. Does anyone have any recommendations.
我在下面的代码片段中有嵌套的json对象,并希望找到所有出现的'$ schema'并将包含该架构值的整个对象保存到另一个对象中。我尝试使用lodash过滤器,但是没有成功。有没有人有任何建议。
{
"element": "parseResult",
"content": [
{
"element": "category",
"meta": {
"classes": [
"api"
],
"title": "Test"
},
"attributes": {
"meta": [
{
"element": "member",
"meta": {
"classes": [
"user"
]
},
"content": {
"key": {
"element": "string",
"content": "FORMAT"
},
"value": {
"element": "string",
"content": "1A"
}
}
}
]
},
"content": [
{
"element": "category",
"meta": {
"classes": [
"resourceGroup"
],
"title": "Questions"
},
"content": [
{
"element": "resource",
"meta": {
"title": "Questions"
},
"attributes": {
"href": "/questions"
},
"content": [
{
"element": "transition",
"meta": {
"title": "List All Questions"
},
"content": [
{
"element": "httpTransaction",
"content": [
{
"element": "httpRequest",
"attributes": {
"method": "GET"
},
"content": []
},
{
"element": "httpResponse",
"attributes": {
"statusCode": "200",
"headers": {
"element": "httpHeaders",
"content": [
{
"element": "member",
"content": {
"key": {
"element": "string",
"content": "Content-Type"
},
"value": {
"element": "string",
"content": "application/json"
}
}
}
]
}
},
"content": [
{
"element": "dataStructure",
"content": [
{
"element": "Question List"
}
]
},
{
"element": "asset",
"meta": {
"classes": [
"messageBody"
]
},
"attributes": {
"contentType": "application/json"
},
"content": "[\n {\n \"question\": \"Favourite programming language?\",\n \"published_at\": \"2014-11-11T08:40:51.620Z\",\n \"url\": \"/questions/1\",\n \"choices\": [\n {\n \"choice\": \"Javascript\",\n \"url\": \"/questions/1/choices/1\",\n \"votes\": 2048\n }\n ]\n }\n]"
},
{
"element": "asset",
"meta": {
"classes": [
"messageBodySchema"
]
},
"attributes": {
"contentType": "application/schema+json"
},
"content": "{\n \"$schema\": \"http://json-schema.org/draft-04/schema#\",\n \"type\": \"array\"\n}"
}
]
}
]
}
]
}
]
},
{
"element": "resource",
"meta": {
"title": "Question"
},
"attributes": {
"href": "/questions/{id}",
"hrefVariables": {
"element": "hrefVariables",
"content": [
{
"element": "member",
"attributes": {
"typeAttributes": [
"required"
]
},
"content": {
"key": {
"element": "string",
"content": "id"
},
"value": {
"element": "number",
"content": 1234
}
}
}
]
}
},
"content": [
{
"element": "transition",
"meta": {
"title": "Retrieve Question"
},
"content": [
{
"element": "httpTransaction",
"content": [
{
"element": "httpRequest",
"attributes": {
"method": "GET"
},
"content": []
},
{
"element": "httpResponse",
"attributes": {
"statusCode": "200",
"headers": {
"element": "httpHeaders",
"content": [
{
"element": "member",
"content": {
"key": {
"element": "string",
"content": "Content-Type"
},
"value": {
"element": "string",
"content": "application/json"
}
}
}
]
}
},
"content": [
{
"element": "dataStructure",
"content": [
{
"element": "Question"
}
]
},
{
"element": "asset",
"meta": {
"classes": [
"messageBody"
]
},
"attributes": {
"contentType": "application/json"
},
"content": "{\n \"question\": \"Favourite programming language?\",\n \"published_at\": \"2014-11-11T08:40:51.620Z\",\n \"url\": \"/questions/1\",\n \"choices\": [\n {\n \"choice\": \"Javascript\",\n \"url\": \"/questions/1/choices/1\",\n \"votes\": 2048\n }\n ]\n}"
},
{
"element": "asset",
"meta": {
"classes": [
"messageBodySchema"
]
},
"attributes": {
"contentType": "application/schema+json"
},
"content": "{\n \"$schema\": \"http://json-schema.org/draft-04/schema#\",\n \"type\": \"object\",\n \"properties\": {\n \"question\": {\n \"type\": \"string\"\n },\n \"published_at\": {\n \"type\": \"string\"\n },\n \"url\": {\n \"type\": \"string\"\n },\n \"choices\": {\n \"type\": \"array\"\n }\n },\n \"required\": [\n \"question\",\n \"published_at\",\n \"url\",\n \"choices\"\n ]\n}"
}
]
}
]
}
]
}
]
}
]
},
{
"element": "category",
"meta": {
"classes": [
"dataStructures"
]
},
"content": [
{
"element": "dataStructure",
"content": [
{
"element": "object",
"meta": {
"id": "Question"
},
"content": [
{
"element": "member",
"attributes": {
"typeAttributes": [
"required"
]
},
"content": {
"key": {
"element": "string",
"content": "question"
},
"value": {
"element": "string",
"content": "Favourite programming language?"
}
}
},
{
"element": "member",
"attributes": {
"typeAttributes": [
"required"
]
},
"content": {
"key": {
"element": "string",
"content": "published_at"
},
"value": {
"element": "string",
"content": "2014-11-11T08:40:51.620Z"
}
}
},
{
"element": "member",
"attributes": {
"typeAttributes": [
"required"
]
},
"content": {
"key": {
"element": "string",
"content": "url"
},
"value": {
"element": "string",
"content": "/questions/1"
}
}
},
{
"element": "member",
"attributes": {
"typeAttributes": [
"required"
]
},
"content": {
"key": {
"element": "string",
"content": "choices"
},
"value": {
"element": "array",
"content": [
{
"element": "Choice"
}
]
}
}
}
]
}
]
},
{
"element": "dataStructure",
"content": [
{
"element": "object",
"meta": {
"id": "Choice"
},
"content": [
{
"element": "member",
"attributes": {
"typeAttributes": [
"required"
]
},
"content": {
"key": {
"element": "string",
"content": "choice"
},
"value": {
"element": "string",
"content": "Javascript"
}
}
},
{
"element": "member",
"attributes": {
"typeAttributes": [
"required"
]
},
"content": {
"key": {
"element": "string",
"content": "url"
},
"value": {
"element": "string",
"content": "/questions/1/choices/1"
}
}
},
{
"element": "member",
"attributes": {
"typeAttributes": [
"required"
]
},
"content": {
"key": {
"element": "string",
"content": "votes"
},
"value": {
"element": "number",
"content": 2048
}
}
}
]
}
]
},
{
"element": "dataStructure",
"content": [
{
"element": "array",
"meta": {
"id": "Question List"
},
"content": [
{
"element": "Question"
}
]
}
]
}
]
}
]
}
]
}
I tried this as a solution.
我试过这个解决方案。
function getObject(theObject) {
var result = null;
if(theObject instanceof Array) {
for(var i = 0; i < theObject.length; i++) {
result = getObject(theObject[i]);
}
}
else
{
for(var prop in theObject) {
console.log(prop + ': ' + theObject[prop]);
if(prop == '$schema') {
if(theObject[prop] == 'http://json-schema.org/draft-04/schema#') {
return theObject;
}
}
if(theObject[prop] instanceof Object || theObject[prop] instanceof Array)
result = getObject(theObject[prop]);
}
}
return result;
}
var result = getObject(json);
1 个解决方案
#1
1
Jacob,
The problem is in your JSON itself. Your json is a key/value pair. Keys can be strings (surrounded with "quotes") to enable properties that have spaces or special characters. e.g.
问题出在你的JSON本身。你的json是一个键/值对。键可以是字符串(用“引号”包围)以启用具有空格或特殊字符的属性。例如
var obj = { "my property": "my value" };
var val = obj["my property"] // "my value";
However your values should only have quotes around them if they are strings, otherwise it won't get parsed to an object - it will remain in string representation.
但是,如果它们是字符串,那么你的值应该只有它们周围的引号,否则它将不会被解析为一个对象 - 它将保留在字符串表示中。
var obj = { "foo" : "{ \"bar\" : \"my value\" }" } // notice I had to escape the strings with backslashes \
var val = obj.foo.bar // error because foo is a string with the value "{ "bar" : "my value" }"
In your json, the value of the content property is a string:
在你的json中,content属性的值是一个字符串:
"content": "{\n \"$schema\": \"http://json-schema.org/draft-04/schema#\",\n \"type\": \"array\"\n}"
The fact that you needed to escape your quotes with \ tells you this as well. If you expect the content to be parsed the first time, then it should look something like this:
你需要用\来逃避你的引号这一事实也告诉你。如果您希望第一次解析内容,那么它应该如下所示:
"content": { "$schema": "http://json-schema.org/draft-04/schema#", "type": "array" }
If you can't change this, then you can call an eval() or a JSON.parse() on the content to parse the string to an object (this can be unsafe if your content is coming from the users).
如果你不能改变它,那么你可以在内容上调用eval()或JSON.parse()来将字符串解析为一个对象(如果你的内容来自用户,这可能是不安全的)。
Edit: Because you cannot change the JSON coming in, I created a function called deepParseObject. It's by no means error-proof, but I think it will work for your situation:
编辑:因为您无法更改进入的JSON,所以我创建了一个名为deepParseObject的函数。它绝不是防错的,但我认为它适用于您的情况:
function deepParseObject(theObject) {
for(var prop in theObject) {
if(typeof theObject[prop] === "string" && (theObject[prop].indexOf('{') == 0 || theObject[prop].indexOf('[') == 0)) {
theObject[prop] = JSON.parse(theObject[prop]);
}
if(theObject[prop] instanceof Object || theObject[prop] instanceof Array)
deepParseObject(theObject[prop]);
}
}
What it does is parse the content properties if their values are strings and start with a {
or [
. After that you can call my original getObject function. Here is the plunker. https://plnkr.co/edit/h06wuAxZkxhwCAho3OK6
它的作用是解析内容属性,如果它们的值是字符串并以{或[。之后,您可以调用我原来的getObject函数。这是plunker。 https://plnkr.co/edit/h06wuAxZkxhwCAho3OK6
I call deepParseObject in the data.js and I'm only using AngularJS to output the results... and because I like Angular :).
我在data.js中调用deepParseObject,我只使用AngularJS输出结果......因为我喜欢Angular :)。
#1
1
Jacob,
The problem is in your JSON itself. Your json is a key/value pair. Keys can be strings (surrounded with "quotes") to enable properties that have spaces or special characters. e.g.
问题出在你的JSON本身。你的json是一个键/值对。键可以是字符串(用“引号”包围)以启用具有空格或特殊字符的属性。例如
var obj = { "my property": "my value" };
var val = obj["my property"] // "my value";
However your values should only have quotes around them if they are strings, otherwise it won't get parsed to an object - it will remain in string representation.
但是,如果它们是字符串,那么你的值应该只有它们周围的引号,否则它将不会被解析为一个对象 - 它将保留在字符串表示中。
var obj = { "foo" : "{ \"bar\" : \"my value\" }" } // notice I had to escape the strings with backslashes \
var val = obj.foo.bar // error because foo is a string with the value "{ "bar" : "my value" }"
In your json, the value of the content property is a string:
在你的json中,content属性的值是一个字符串:
"content": "{\n \"$schema\": \"http://json-schema.org/draft-04/schema#\",\n \"type\": \"array\"\n}"
The fact that you needed to escape your quotes with \ tells you this as well. If you expect the content to be parsed the first time, then it should look something like this:
你需要用\来逃避你的引号这一事实也告诉你。如果您希望第一次解析内容,那么它应该如下所示:
"content": { "$schema": "http://json-schema.org/draft-04/schema#", "type": "array" }
If you can't change this, then you can call an eval() or a JSON.parse() on the content to parse the string to an object (this can be unsafe if your content is coming from the users).
如果你不能改变它,那么你可以在内容上调用eval()或JSON.parse()来将字符串解析为一个对象(如果你的内容来自用户,这可能是不安全的)。
Edit: Because you cannot change the JSON coming in, I created a function called deepParseObject. It's by no means error-proof, but I think it will work for your situation:
编辑:因为您无法更改进入的JSON,所以我创建了一个名为deepParseObject的函数。它绝不是防错的,但我认为它适用于您的情况:
function deepParseObject(theObject) {
for(var prop in theObject) {
if(typeof theObject[prop] === "string" && (theObject[prop].indexOf('{') == 0 || theObject[prop].indexOf('[') == 0)) {
theObject[prop] = JSON.parse(theObject[prop]);
}
if(theObject[prop] instanceof Object || theObject[prop] instanceof Array)
deepParseObject(theObject[prop]);
}
}
What it does is parse the content properties if their values are strings and start with a {
or [
. After that you can call my original getObject function. Here is the plunker. https://plnkr.co/edit/h06wuAxZkxhwCAho3OK6
它的作用是解析内容属性,如果它们的值是字符串并以{或[。之后,您可以调用我原来的getObject函数。这是plunker。 https://plnkr.co/edit/h06wuAxZkxhwCAho3OK6
I call deepParseObject in the data.js and I'm only using AngularJS to output the results... and because I like Angular :).
我在data.js中调用deepParseObject,我只使用AngularJS输出结果......因为我喜欢Angular :)。