Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Supporting serialization of objects with circular references #2

Open
anthonykhoa opened this issue Nov 6, 2020 · 0 comments
Open

Comments

@anthonykhoa
Copy link

anthonykhoa commented Nov 6, 2020

This issue was first mentioned in the post-robot repo:
krakenjs/post-robot#77

The issue

This repo currently does not support the serialization of objects with circular references.

Check out a reproduction of the error by going here(have console open)
https://circle.khoa.app/error/zoid.html

In the console, notice that only the object without a circular reference is logged the correct value { exciting: "llama" }. The other object has a circular reference, and is logged the incorrect value
Screen Shot 2020-11-05 at 5 09 33 PM
This is the child window that gets rendered when someone clicks on StartZoidDemo. It is where the two logged objects are initialized
https://circle.khoa.app/error/zoid2.html

@bluepnume what do you think about this potential solution to support the serialization of objects with circular references?

Summary of solution

Assign each circular reference object a string name, and save as a key-value pair in a hashmap. In the object to be serialized, use the hashmap to convert all circular references to the right string name. After JSON.parse, use the hashmap to convert all string names found as keys in the hashmap to the correct value(a circular reference object)

To serialize

originalObj is the object to be serialized

Steps 2-4 can be skipped if no circular references were found in step 1

  1. Cycle through originalObj, put each circular reference into a hashmap __POST_ROBOT__circularRefs
    Each time a value is an object, add the object as a key to a countRefsHash that uses the Map object.
    The corresponding value to the key is a number that counts the number of times the reference has been encountered in originalObj

    Data structure for countRefsHash:

    { [object]: num } // num equals 1 when an object first gets added to countRefsHash as a key
    

    To get a string name to use as a reference, a variable refNum is used. Initialize refNum with 0.
    Each time the count of a reference equals 2 after someone adds to the count, increment refNum by 1 and:

    1. Add to refsNameHash with the object as a key, and a name as the value. Use Map object.
      Data structure for refsNameHash:
      { [object]: '[$Circular_Ref<refNum>]' }

    2. Add object to __POST_ROBOT__circularRefs
      Data structure for __POST_ROBOT__circularRefs:
      { '[$Circular_Ref<refNum>]': { ...object } }

  2. Convert all circular refs in __POST_ROBOT__circularRefs to the right string name
    Cycle through __POST_ROBOT__circularRefs, and for each value check if the value contains any objects that are also in the refsNameHash as a key. If found, convert those objects to the correct string name using refsNameHash.get(object).

  3. Convert all circular refs in originalObj to the right string name
    Cycle through originalObj, and for each value check if the value contains any objects that are also in the refsNameHash as a key. If found, convert those objects to the correct string name using refsNameHash.get(object).

  4. Add __POST_ROBOT__circularRefs to originalObj

    __POST_ROBOT__circularRefs cannot be added to originalObj before it converts all circular references to the correct string names.

    If it is added before originalObj coverts all circular references to the correct string name, then the value of each property of __POST_ROBOT__circularRefs will be considered a circular reference and therefore converted to a string name.

  5. JSON.stringify
    originalObj is now ready for the JSON.stringify call

Serialization now done

To deserialize

  1. get originalObj from the JSON.parse call. If __POST_ROBOT__circularRefs is not found as a key in originalObj, then skip steps 2-4

  2. Set a variable equal to __POST_ROBOT__circularRefs and delete __POST_ROBOT__circularRefs from originalObj.

  3. Replace each circular Ref string found in __POST_ROBOT__circularRefs with the correct value(a circular ref)
    Cycle through __POST_ROBOT__circularRefs. If any value is a key of __POST_ROBOT__circularRefs, then convert that value to __POST_ROBOT__circularRefs[key].

  4. Replace each circular Ref string found in originalObj with the correct value(a circular ref)
    Cycle through originalObj. If any value is a key of __POST_ROBOT__circularRefs, then convert that value to __POST_ROBOT__circularRefs[key]

Deserialization now done

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant