Encoding an object in TypeScript with functions and a looping reference network

Currently, I'm dealing with a complex project in TypeScript that heavily relies on object-oriented programming, resulting in a quite intricate object graph (including objects that indirectly point to themselves). My need now is to serialize this graph into a string. Is there any way to achieve this in TypeScript without losing crucial information during de-serialization?

Ideally, I am looking for a solution that minimizes the required bookkeeping on each new class added.

Here are some methods I have experimented with:

  1. JSOG. Unfortunately, this approach was unsuccessful because upon de-serialization, the objects were left as type Object and lost their associated methods.

  2. TypedJSON. This method also failed due to the

    Uncaught TypeError: cyclic object value
    error.

  3. A combination of both approaches: Despite trying to pass an object created by jsog-typescript to TypedJSON, it was rejected for not being the correct type.

Answer №1

I pondered the issue of circular references and class simultaneously, which led me to create a package that addresses this concern.

https://github.com/denostack/superserial

One striking demonstration of the capabilities of this library:

import { Serializer } from 'superserial'

const serializer = new Serializer()

{
  // Illustrating a recursive map
  const map = new Map();
  map.set(map, map);

  const serialized = serializer.serialize(map);
  console.log(serialized); // output: Map($0=>$0)

  const deserialized = serializer.deserialize("Map($0=>$0)");

  console.log(deserialized === [...deserialized.keys()][0]); // true
  console.log(deserialized === deserialized.get([...deserialized.keys()][0])); // true
}

{
  // Demonstrating nested objects and recursion
  const obj = { foo: { bar: {} } }
  obj.foo.bar.baz = obj

  const serialized = serializer.serialize(obj);
  console.log(serialized); // output: {"foo":$1};{"bar":$2};{"baz":$0}

  const deserialized = serializer.deserialize('{"foo":$1};{"bar":$2};{"baz":$0}');

  console.log(deserialized) // output: <ref *1> { foo: { bar: { baz: [Circular *1] } } }
  console.log(deserialized.foo.bar.baz === deserialized) // true
}

Answer №2

Ultimately, I decided to create my own serialization tool

Answer №3

While the original author may have posted this information late, it could still be beneficial to others.

We encountered a similar issue with circular references and experimented with various Object-Oriented Programming (OOP) techniques involving polymorphic structures. Despite trying popular serializers like class-transformer and TypedJSON, we found they did not fully meet our needs in a convenient manner.

In response, we developed our own open-source serializer, which can be found here:

https://github.com/dipscope/TypeManager.TS

This serializer offers multiple solutions for handling circular object references and provides customization options.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Utilizing the String Enum for mapping an interface with an index

Using Typescript, I aim to make use of my string enumeration: export const enum MutationKeys { registerUser = 'registration/REGISTER', registerUserCompleted = 'registration/REGISTER_COMPLETED' } This allows the string values t ...

Could you please clarify the type of event on the onInputChange props?

I am encountering an issue with using React.ChangeEvent on the mui v4 autocomplete component as I prefer not to use any other method. However, I keep getting an error indicating that the current event is incompatible. const handle = (e: React.ChangeEv ...

What about incorporating unique images with custom HTML input tags?

Hand Diagram Hey there! I'm currently working on a small project using Angular. I was wondering if it's feasible to add tags to an image and prompt the user for input when a tag is clicked? For example, in the image above, I'd like to plac ...

Finding out whether the current date falls between a startDate and endDate within a nested object in mongoose can be done by using a specific method

My data structure includes a nested object as shown: votingPeriod: {startDate: ISOdate(), endDate: ISOdate()}. Despite using the query below, I am getting an empty object back from my MongoDB. const organizations = await this.organizationRepository.find( ...

Discover the type of an object in TypeScript

I am searching for a method to create a "mapped" object type in TypeScript. Here are the typings I currently have: interface Factory<T>{ serialize: (val: T)=>void, deserialize: ()=>T, } interface MyDict{ [key: string]: Factory& ...

Adding a JSON object to an API call: step-by-step guide

I have a variety of Objects stored in an array that are generated dynamically. My goal is to save each Object separately by sending it through an API. The challenge lies in the fact that there can be numerous Objects in the array. What would be the most ef ...

Why are my animation states being shared among different instances of the component?

Why is the animation playing for both instances of the carousel component when interacting with just one call (e.g. clicking next or prev)? carousel.component.ts @Component({ selector: 'app-carousel', standalone: true, templateUrl: './c ...

Setting up the Angular2 library with a defaultExtension for systemjs configuration

Can I automate the setup of an npm repository for Angular2 to handle the systemjs config with default extensions? I'm currently working on ng2-orm and wondering if it's possible to streamline this process during npm installation. Although my pa ...

The upcoming router is not compatible with the NextPage type

I am currently working on introducing dynamic routing into an application that was originally designed with static routes. However, I am facing some confusion as I encounter TypeScript errors that are difficult for me to understand. Below is the code snipp ...

What purpose does the pipe method serve in RxJS?

It seems like I understand the basic concept, but there are a few unclear aspects. Here is my typical usage pattern with an Observable: observable.subscribe(x => { }) If I need to filter data, I can achieve this by: import { first, last, map, reduce, ...

Displaying errors from an API using Angular Material mat-error

I am currently working on a form that includes an email field. Upon saving the form, the onRegisterFormSubmit function is called. Within this function, I handle errors returned by the API - specifically setting errors in the email form control and retrie ...

Sending JSON object data to an API endpoint using the POST method in an Angular application

Attempted to post data to an API, but received a 400 bad request error. After testing with Postman, it seems that the issue may lie within my service or TypeScript code. As a newcomer to Angular, I am seeking assistance as I have searched extensively witho ...

Error: No 'map' property found in 'TwitterserviceService' type

Currently, I am in the process of learning how to develop simple and basic Angular applications. As part of my learning journey, I decided to incorporate my Twitter timeline into one of my projects. To aid me in this endeavor, I referred to various online ...

Problems arise during the installation of TypeScript typings for .NET Core

After downloading VS2015 community edition, I decided to migrate one of my old MVC projects to .NET Core MVC. I used TypeScript for all the client side code in my old project, but now it's becoming a hassle to set up. Despite configuring multiple JSON ...

One-liner in TypeScript for quickly generating an object that implements an interface

In Typescript, you can create an object that implements an interface using a single expression like this: => return {_ : IStudent = { Id: 1, name: 'Naveed' }}; Is it possible to achieve this in just one statement without the need for separate ...

There seems to be an issue with Material-UI and TypeScript where a parameter of type 'string' does not have an index signature in the type 'ClassNameMap<"container" | "navBar" | "section0">'

My current project is encountering a TS Error stating "(No index signature with a parameter of type 'string' was found on type 'ClassNameMap<"container" | "navBar" | "section0">'.)" The code below is used to assign styles to vari ...

Angular firebase Error: The parameter 'result' is missing a specified type and is implicitly assigned the 'any' type

I have encountered an issue with the code I am working on and both the result and error are throwing errors: ERROR in src/app/login/phone/phone.component.ts(48,75): error TS7006: Parameter 'result' implicitly has an 'any' type. s ...

Calculate the difference between two arrays containing objects using ES6 or TypeScript

I am faced with a challenge involving two arrays: arr1 = [{ id: 1, name: 'Diego', age: 23 }, { id: 2, name: 'Brian', age: 18 }] arr2 = [{ id: 1, name: 'Diego', ag ...

Getting access to a function within the same TypeScript file from another exported function in Angular

I'm having trouble accessing a function from another export function within the same TypeScript file. Can anyone help me with this? app.component.ts: import { Component } from '@angular/core'; @Component({ selector: 'app-root', ...

Is it possible to silence the other person's audio using livekit?

As a developer, I create meeting apps using React and livekit technology. I am looking for a reliable method to silence the audio of other participants in the virtual room. Any suggestions? ...