friends. I'm trying to write code that hashes all values in a JSON file, regardless of file structure, while preserving the keys and structure. I'm new to javascript, and am having some trouble. My code hashes the values of big and baz, but doesn't recursively hash the values of cat and bar like I want it to. Ideally, I want the numbers hashed and the names (big, foo, etc.) left alone. Thank you so much! See my code below:
var meow = {
big: 20,
baz: {
foo: {
cat: 3,
bar: 5
}
}
};
console.log(typeof(meow.baz.foo));
function hashobj(obj)
{
var valarray = Object.keys(obj);
var zer = valarray[0];
for(var i = 0; i < valarray.length; i++)
{
var vaz = valarray[i];
if(typeof(obj[vaz] != "object"))
{
obj[vaz] = sha256(obj[vaz] + buf);
}
if(typeof(obj[vaz]) == "object")
{
console.log("HERE");
hashobj(obj[vaz]);
}
}
}
hashobj(meow);
console.log(meow);
If you're looking to do this recursively, I would suggest using a generic transformation function that handles the recursive object structure and delegates to a supplied function the actual work of transforming the leaf nodes.
In this version, the transform
function does all the heavy lifting. It calls the supplied function on scalar values and recursively calls itself on objects and arrays, recreating the structure of the original with the new values. This is quite reusable.
We create our hashObject
function by passing transform
a function which does the sha256 encoding of our values.
const transform = (fn) => (obj) =>
Array.isArray (obj)
? obj .map (transform (fn))
: Object (obj) === obj
? Object .fromEntries (Object .entries (obj)
.map (([k, v]) => [k, transform (fn) (v)])
)
: fn (obj)
const hashObj = transform ((n) => sha256 (String (n)))
const meow = {big: 20, baz: {foo: {cat: 3, bar: 5, qux: [1, 2, 3]}}};
// added to demonstrate arrays --------^
console .log (hashObj (meow))
.as-console-wrapper {max-height: 100% !important; top: 0}
<script src="https://unpkg.com/js-sha256@0.9.0/src/sha256.js"></script>
This isn't a well-formed tree data structure where children are hold by a unqiue property, but the shape arise from abritrarily nested objects and arrays. I think I will implement a general enough, recursive left and right fold for such tree-like structures to be able to traverse it in pre- and post-order respecively. having such general folds would allow us to abstract the recurison anf focus on the task at hand.
@scriptum: that would be quite useful. The above is not meant for traversals, although similar techniques could be used for that. (Some of the work from user Thankyou probably offers suggestions in that direction.) If you're thinking that such pre-/post-order traversals could then be used to solve this sort of transformation problem, I'd be curious to see how.
I dunno yet but the value passed to the reducing function is probably the whole object at your current position, so that you can add new or delete existing props. On the other hand there are probably not that many operations that are performed at all leafs/data notes uniformly as in your example. So it's probably a silly idea and lenses/prisms are a better choice..
@scriptum: I think there may be a lot of merit in it. I'd be curious to see it work. I've used variants of the above that pass both the key and the value to the transforming function; that makes sense. I'd be curious to see if something passing the equivalent output object for the node would be useful.
Ohhh a very elegant solution. I hope to one day write code like this. Thank you for your contribution!