I have the following json that is quite complex and detailed.
I need to extrapolate information (text) from the json only if the resource-id
contains the following text "com.shazam.android:id/"
and if it contains the following props (["title", "subtitle", "datetime"]
).
If last element does not contain a datetime
then resorceIdFinal
is not inserted.
Below is an example json I want to get.
Here you can find the json I use, I couldn’t insert it here due to character space.
Link: 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 result I would like to get:
[
{
"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"
}
]
Can you give me a hand?
2
Answers
This function recursively calls itself, but ignores the result of that call:
Nothing is ever done with the return value of
getChildren(el.children, replaceText, props, resorceIdFinal)
. Perhaps the intent was to add that result to thearr
array?:Note that there is a lot of code here, and this answer makes no guarantee that this is the only problem in the code shown. But it at least appears to be the most relevant to the problem described. You are encouraged to use a debugger to narrow down any additional problems, asking a separate question if any are found.
In continuation from comments, provided your requirements haven’t changed significantly, the data to be extracted can be done so by treating the json string on a "line by line" basis.
From looking at the desired output and the source json, it is the
text
attributes in the json structure that then become title, subtitle, and datetime. As such, when any attribute namedtext
comes along (linearly), then the algorithm saves it as being the last encountered. Next when a desired sentinel is encountered, each of these:… The previously (or last) saved
text
attribute is assigned to be that property.When datetime is recorded, this is assumed to be the end of the record and it is pushed onto an array so that the next record if any can then be progressively built in the same fashion.
The rest is explained by way the code itself and code comments.
This is a working example. Copy and paste the json into the textarea then click the button. The json must be complete because it tries to parse it first, then stringifies so that its properly separated into lines. These steps can be commented out when you already know the input is separated into lines.