Right?
However, since the number can change, I tried to capture it first using a RegEx and getting it into a variable, then place the variable inside the JSONValue variable, but I can't get that to work.
Plus, of course, there is that darn "/12" inside the JSONValue path, which could further complicate things.
How do I get and set the value of HDE when the path towards the value can change because of that number code?
If you had valid JSON (I've pruned the non-JSON commas from your source, below), you might be able use something like the function in the macro below.
(But JSON parsing would simply fail with the example which you show above โ trailing commas are valid in JS source, but not in JSON.
Not sure how your source is being formed, but if you can parse it in a JavaScript interpreter to an JS Object, then you would be able to obtain genuine JSON with JSON.stringify(obj);
const main = () =>
either(
message => message
)(
valueFound => valueFound
)(
bindLR(
jsonParseLR(kmvar.local_JSON)
)(
atDeepKeyLR(kmvar.local_Key)
)
);
// ---- FIRST VALUE FOUND AT POSSIBLY NESTED KEY -----
// atDeepKeyLR :: String -> Dict -> Either String a
const atDeepKeyLR = k =>
// Just the first value found at a matching key at
// any level of a possibly nested object, or
// Nothing if no value is found.
dict => {
const f = acc => subKey => obj => {
const v = obj[subKey];
return "object" === typeof v
? go(v)
: acc;
};
const go = obj =>
k in obj
? Right(obj[k])
: Object.keys(obj).reduce(
(a, subKey) =>
"Right" in a
? a
: f(a)(subKey)(obj),
Left(`"${k}" not found in:\n${JSON.stringify(dict, null, 2)}`)
);
return go(dict);
};
// --------------------- GENERIC ---------------------
// Left :: a -> Either a b
const Left = x => ({
type: "Either",
Left: x
});
// Right :: b -> Either a b
const Right = x => ({
type: "Either",
Right: x
});
// bindLR (>>=) :: Either a ->
// (a -> Either b) -> Either b
const bindLR = lr =>
// Bind operator for the Either option type.
// If lr has a Left value then lr unchanged,
// otherwise the function mf applied to the
// Right value in lr.
mf => "Left" in lr
? lr
: mf(lr.Right);
// either :: (a -> c) -> (b -> c) -> Either a b -> c
const either = fl =>
// Application of the function fl to the
// contents of any Left value in e, or
// the application of fr to its Right value.
fr => e => "Left" in e
? fl(e.Left)
: fr(e.Right);
// jsonParseLR :: String -> Either String a
const jsonParseLR = s => {
try {
return Right(JSON.parse(s));
} catch (e) {
return Left(
[
e.message,
`(line:${e.line} col:${e.column})`
].join("\n")
);
}
};
// MAIN ---
return main();