0

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, []);
}

4
  • "serializing" means creating a character string representation. But your function returns an object structure.
    – trincot
    Commented Jul 8 at 14:57
  • Welcome to Stack Overflow! Please edit to describe your problem clearly enough for people to help you. Are you trying to get someone to debug/fix your implementation? If so, please tell us what is wrong with it. Are you trying to get someone to verify*/*improve your implementation? If so you might want to post this to the Code Review stack exchange instead (although there are criteria for posting there, so make sure to follow their rules if you do this). Are should we ignore your implementation and come up with our own like this playground link? Please let us know.
    – jcalz
    Commented Jul 8 at 16:29
  • Hi @jcalz Below response I am getting obj3A: { "foo": "bar" }, obj3B: { $ref : #/Obj3A}, paths: { "/circle": { obj2: { circle: { $ref:"#/paths/~1circle/obj2" } } } } } If you check value of Obj3A and Obj3B is same , and due repeated same values this happening Commented Jul 8 at 18:48
  • “Below”? I don’t understand, below where?
    – jcalz
    Commented Jul 8 at 19:34

0