Reputation: 1
I have an object structure where circular references need to be represented using $ref
annotations in the output.
Here is an example of the input and expected output :-
Input is -
const obj2 = { circle: {} }; obj2.circle = obj2;
const obj3 = { foo: 'bar' };
const obj = {
obj3A: obj3,
obj3B: obj3,
paths: {
'/circle': {
obj2: {}
}, }, };
obj.paths['/circle'].obj2 = obj2;
EXPECTED OUTPUT -
obj3A: { "foo": "bar" },
obj3B: { "foo": "bar" },
paths: {
"/circle": {
obj2: {
circle: {
$ref:"#/paths/~1circle/obj2" } } } } }
obj2
contains a circular reference to itself, represented by $ref
. How can I implement a TypeScript function to achieve this output when serializing objects?
for repeated value and non circular references should represent with value as I shown I output and for circular references in shows like reference
My solution
export function decycle(obj: unknown, replacer?: (value: any) => any) {
const objs = new weakmap<object, string>();
function derez(value: any, path: (string | number)[]): any {
if (replacer) {
value = replacer(value);
}
if (typeof value === 'object' && value !== null) {
const oldPath = objs.get(value);
if (oldPath) {
return { $ref: oldPath };
}
objs.set(value, pathToPointer(path));
if (Array.isArray(value)) {
return value.map((element, i) => derez(element, [...path, i]));
}
const newObj: Record<string, any> = {};
for (const name in value) {
if (Object.prototype.hasOwnProperty.call(value, name)) {
newObj[name] = derez(value[name], [...path, name]);
}
}
return newObj;
}
return value;
}
return derez(obj, []);
}
Upvotes: 0
Views: 41