提问人:Paul 提问时间:9/22/2023 最后编辑:Paul 更新时间:9/27/2023 访问量:89
Js 从 json 中提取信息
Js extract information from a json
问:
我有以下非常复杂和详细的json。
只有当 包含以下文本并且包含以下 props () 时,我才需要从 json 推断信息(文本)。resource-id
"com.shazam.android:id/"
["title", "subtitle", "datetime"]
如果最后一个元素不包含 则不插入 THEN。datetime
resorceIdFinal
下面是我想得到的 json 示例。
在这里你可以找到我使用的json,由于字符空间,我无法在这里插入它。
友情链接: https://pastebin.com/raw/hFLmP2T8
const check = (obj, keys) => !keys.some((el) => !obj.hasOwnProperty(el));
const isObjectEmpty = (objectName) => {
return (
objectName &&
Object.keys(objectName).length === 0 &&
objectName.constructor === Object
);
};
const getChildren = (el, replaceText, props, resorceIdFinal) => {
var arr = [];
el.forEach((el) => {
let resorceId = getResorceId(el.attributes, replaceText, props, resorceIdFinal);
if(!isObjectEmpty(resorceId)) arr.push(resorceId);
//console.log(arr);
getChildren(el.children, replaceText, props, resorceIdFinal);
});
return arr;
};
const getResorceId = (el, replaceText, props, resorceIdFinal) => {
var o = {};
if (el["resource-id"] !== undefined) {
var resorceId = el["resource-id"].replace(replaceText, "");
if (props.includes(resorceId)) {
o = { [resorceId]: el.text };
}
}
return o;
};
function readPro(json, replaceText, props, filterA, resorceIdFinal) {
var arr = [];
json.forEach((el) => {
arr.push(getChildren(el.children, replaceText, props, resorceIdFinal));
});
console.log(arr)
filtered = arr.filter(
((s) => (o) =>
((k) => !s.has(k) && s.add(k))(filterA.map((k) => o[k]).join("|")))(
new Set()
)
);
return filtered;
}
var res = readPro(
a.children,
"com.shazam.android:id/",
["title", "subtitle", "datetime"],
["title", "subtitle"],
"datetime"
);
console.log(res);
我想得到的 Json 结果:
[
{
"title": "Believe",
"subtitle": "Chuther",
"datetime": "12 giu, 16:42"
},
{
"title": "시작 (Inst.)",
"subtitle": "Gaho",
"datetime": "12 giu, 16:42"
},
{
"title": "Give It Up",
"subtitle": "KC and the Sunshine Band",
"datetime": "12 giu, 16:41"
},
{
"title": "GRAVITY",
"subtitle": "Jong Ho",
"datetime": "12 giu, 16:41"
}
]
你能帮我一把吗?
编辑:
const isObjectEmpty = (objectName) =>
(
objectName &&
Object.keys(objectName).length === 0 &&
objectName.constructor === Object
);
const getResorceId = (el, replaceText, props, value) => {
if (el["resource-id"] !== undefined) {
var resorceId = el["resource-id"].replace(replaceText, "");
if (props.includes(resorceId)) {
return { [resorceId]: el[value] };
}
}
return {};
};
const getChildren = (el, replaceText, props, value) => {
var arr = [];
el.forEach((el) => {
let resorceId = getResorceId(el.attributes, replaceText, props, value);
var o = {}
if (!isObjectEmpty(resorceId)) {
arr.push(resorceId);
for (const [_, value] of Object.entries(arr)) {
for (const [key, value2] of Object.entries(value))
o[key] = value2
}
arr = [o]
}
arr.push(...getChildren(el.children, replaceText, props, value));
});
//console.log(arr.length, arr)
//if(arr.length === 1 && !Object.hasOwn(...arr, resorceIdFinal)) arr = []
return arr
};
function readPro(json, replaceText, props, filterA, value) {
var arr = [];
json.forEach((el) => {
arr.push(...getChildren(el.children, replaceText, props, value));
});
filtered = arr.filter(
((s) => (o) =>
((k) => !s.has(k) && s.add(k))(filterA.map((k) => o[k]).join("|")))(
new Set()
)
);
return filtered;
}
var rA = readPro(
a.children,
"com.shazam.android:id/",
["title", "subtitle", "datetime"],
["title", "subtitle"],
"text"
);
答:
此函数以递归方式调用自身,但忽略该调用的结果:
const getChildren = (el, replaceText, props, resorceIdFinal) => {
var arr = [];
el.forEach((el) => {
let resorceId = getResorceId(el.attributes, replaceText, props, resorceIdFinal);
if(!isObjectEmpty(resorceId)) arr.push(resorceId);
//console.log(arr);
getChildren(el.children, replaceText, props, resorceIdFinal);
});
return arr;
};
返回值 不会执行任何操作。也许目的是将该结果添加到数组中?getChildren(el.children, replaceText, props, resorceIdFinal)
arr
const getChildren = (el, replaceText, props, resorceIdFinal) => {
var arr = [];
el.forEach((el) => {
let resorceId = getResorceId(el.attributes, replaceText, props, resorceIdFinal);
if(!isObjectEmpty(resorceId)) arr.push(resorceId);
//console.log(arr);
arr.push(...getChildren(el.children, replaceText, props, resorceIdFinal));
});
return arr;
};
请注意,这里有很多代码,这个答案不能保证这是所示代码中的唯一问题。但它至少看起来与所描述的问题最相关。建议使用调试器来缩小任何其他问题的范围,如果发现任何问题,请单独询问。
评论
在注释的延续中,如果您的要求没有发生重大变化,则可以通过“逐行”处理 json 字符串来提取要提取的数据。
通过查看所需的输出和源 json,json 结构中的属性将成为 title、subtitle 和 datetime。因此,当任何命名的属性出现(线性)时,算法会将其保存为最后遇到的属性。接下来,当遇到所需的哨兵时,以下每个哨兵:text
text
com.shazam.android:id/title
com.shazam.android:id/subtitle
com.shazam.android:id/datetime
...将以前(或上次)保存的属性指定为该属性。
记录日期时间时,假定这是记录的末尾,并将其推送到数组上,以便可以以相同的方式逐步构建下一条记录(如果有)。text
其余的则通过代码本身和代码注释来解释。
这是一个工作的例子。将 json 复制并粘贴到 textarea 中,然后单击按钮。json 必须是完整的,因为它首先尝试解析它,然后字符串化,以便将其正确分隔成行。当您已经知道输入已分隔成行时,可以注释掉这些步骤。
function extract( input_json ) {
// In the event that the source json is not already broken into lines:
try {
let _parsed = JSON.parse( input_json );
input_json = JSON.stringify(_parsed , null, 1);
}
catch (e) {
console.log("Error parsing json");
return false;
}
// Turn into an array, one line per index
let json_lines = input_json.split("\n");
// Now onto a linear scan/search to gather the pertinent data
let output = []; // this will hold the end result
let last_passed_text = ''; // this will be the last "text" attribute's value encountered
let current_record = {}; // this will hold the current record being built progressively
for (let i = 0; i < json_lines.length; i++) {
let textPos = json_lines[i].indexOf('"text"');
if ( textPos > -1) {
let _firstColon = json_lines[i].indexOf(":");
if (_firstColon > textPos) {
// split by colon since `"text" :` indicates definition desired
let relevantPart = json_lines[i].substring( _firstColon + 1).trim(); // characters after colon to end of string, trimmed
try {
relevantPart = decodeURIComponent( relevantPart ); // just in case
}
catch {}
// assume that characters after colon behave as `"abcdef",` and if not it doesn't matter, e.g. boolean values
let token = relevantPart.substring(1,relevantPart.length-2); // get value between the assumed double quotes, -2 because of trailing comma, if any
last_passed_text = token.toString(); // de-ref
// console.log("last_passed_text",last_passed_text);
}
}
if ( json_lines[i].indexOf("resource-id") > -1) {
if ( json_lines[i].indexOf("com.shazam.android:id/title") > -1) {
// presence of title always indicates where to start collecting
current_record = {};
current_record.title = last_passed_text.toString(); // de-ref
//console.log("title", current_record.title);
// console.log( json_lines[i], last_passed_text );
}
else if ( json_lines[i].indexOf("com.shazam.android:id/subtitle") > -1) {
current_record.subtitle = last_passed_text.toString(); // de-ref
// console.log( json_lines[i], last_passed_text );
}
else if ( json_lines[i].indexOf("com.shazam.android:id/datetime") > -1) {
current_record.datetime = last_passed_text.toString(); // de-ref
// presence of datetime always indicates where to end collecting
output.push( JSON.parse(JSON.stringify( current_record )) );
// console.log( json_lines[i], last_passed_text );
}
}
}
// console.log(output);
return output;
}
Paste json here: (input)<br>
<textarea id="input-json" rows=15 cols=50></textarea>
<hr>
<button type="button" onclick="
console.log(
extract(
document.getElementById('input-json').value
)
);">Extract To Console</button>
评论
{ "message": "Uncaught URIError: URI malformed", "filename": "https://stacksnippets.net/js", "lineno": 62, "colno": 32 }
评论