npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

salmon-serializer

v1.0.0

Published

this is the serializer of javascript

Downloads

3

Readme

Salmon Serializer

Salmon Serializer is a robust serialization tool for JavaScript, offering easy serialization and deserialization of JavaScript objects, instances, arrays, and functions. It automatically resolves references and circular references, supporting TypeScript decorators for customized serialization processes.

Table of Contents

What is Salmon Serializer?

With the advancement of web technologies and the new generation of desktop and mobile technologies, JavaScript is taking on increasingly complex tasks such as developing large-scale web applications, desktop applications, and even games. We need a serialization tool more powerful than JSON.

Salmon Serializer is dedicated to serializing and deserializing objects that JSON can't. It handles class objects, references to the same object, circular references, and methods, aiming for perfect serialization and deserialization in complex environments.

Installation

# npm
npm install salmon-serialization
# yarn
yarn add salmon-serialization

Quick Start

Object

const objectOnTest = {
    num: 1,
    str: `2`,
    bool: true,
    object2: {
        num: 3,
        str: `4`,
        bool: false,
    }
}

const serialized = await serialize(objectOnTest)

// it will be serialized like this
const serializedOnTest = {
    id: ``,
    typename: `Object`,
    data: {
        num: 1,
        str: `2`,
        bool: true,
        object2: {
            id: ``,
            typename: `Object`,
            data: {
                num: 3,
                str: `4`,
                bool: false,
            }
        }
    }
}

const deserialized = await deserialize(serialized);

Instance

import { deserialize, serialize, SerializableContext } from 'salmon-serializer';

class TestSerializationClass {
    num = 1;
    str = `str2`;
    bool = true;
    testObject = {
        id: `ob1`,
        sth: `testObject`,
    }
    testInstance = new TestSerializationClass2();
}
class TestSerializationClass2 {
    num = 3;
    str = `str4`;
    bool = false;
}

const instanceOnTest = new TestSerializationClass();

// It will be serialized like this
const serializedOnTest = {
    id: ``,
    typename: TestSerializationClass.name,
    data: {
        num: 1,
        str: `str2`,
        bool: true,
        testObject: {
            id: `ob1`,
            typename: `Object`,
            data: {
                id: `ob1`,
                sth: `testObject`,
            }
        },
        testInstance: {
            id: ``,
            typename: TestSerializationClass2.name,
            data: {
                num: 3,
                str: `str4`,
                bool: false,
            }
        }
    }
}

// Need to register the class first
SerializableContext.register(TestSerializationClass, TestSerializationClass2);

const deserialized = await deserialize(serializedOnTest);
// if your are coding with Typescript
// const deserialized = await deserialize<TestSerializationClass>(serializedOnTest);

// remove the class if you need to
// SerializableContext.removeType(TestSerializationClass, TestSerializationClass2);

Methods

serialize

this method serialize any JavaScript things to simple JavaScript Object, And it is an asynchronous method.

import { serialize } from 'salmon-serializer';

// SerializableContext is an optional param
// const serialized = await serialize(anyObject);
const serialized = await serialize(anyObject, new SerializableContext()); 
// ou can output it as json.
conosle.log(JSON.stringify(serialized));

deserialize

this method deserialize it.

import { SerializableContext, deserialize } from 'salmon-serializer';

// SerializableContext is an optional param
// const serialized = await deserialize(serialized);
const deserialized = await deserialize(serialized, new SerializableContext());

SerializableContext.register

if you need to deserialize any class object you need to register the class first

import { SerializableContext } from 'salmon-serializer';

class MyClass {
}

SerializableContext.register(MyClass);

// const myClass = await deserialize(serialized);
// Typescript
// const myClass = await deserialize<MyClass>(serialized);

SerializableContext.removeType

you can remove the class from register list

import { SerializableContext } from 'salmon-serializer';
class MyClass {
}
SerializableContext.register(MyClass);
SerializableContext.removeType(MyClass);

SerializableContext

SerializableContext record all information during serialization or deserialization. Include meta data of classes, referenced objects, exclude or additional objects and your progress call back function.

const serialized = await serialize(instanceUnderTest, new SerializableContext({
   // any object you want to exclude, it won't apperance at serialized object, but you need to add it back when you deserialize it.
   extras: {
       excludeObject: excludeObject,
   }
   // OnProgress can't be called again shorter than inverval ms. 
   interval: -1,
   // lifecycle call back functions
   onStart: startUnderTest,
   // onProgress will be called before each class serialization
   onProgress: progressUnderTest,
   onFinish: finishedUnderTest
}));

SerializableEvent

salmon-serializer cannot serialize 'this' pointer of function, so EventEmitter cannot be serialized perfectly. Another way to resolve is Serializable Event.

class ClassUnderTest {
    onTest = new SerializableEvent();
    number = 0;
    handle(num) {
        this.number = num;
    }
    constructor() {
        this.onTest.on((num)=>this.handle(num), this);
    }
}

const instanceUnderTest = new ClassUnderTest();
const serialized = await serialize(instanceUnderTest);
const deserialized = await deserialize(serialized);
deserialized.onTest.emit(1); //deserialized number will be 1

Decorators

if your are coding with Typescript. It is easy to use decorator to customize serialization or deserialization.

// use Serializable to instead SerializableContext.register
@Serializable()
class ClassUnderTest {
    // ignore any property
    @Ignore()
    id: string = 'test';
    @Ignore()
    testValue: string = 'test1';
    
    // export accessor
    @SerializeField()
    get test() {
        return 'test';
    }
    set test(value: string) {
        this.testValue = value;
    }
}

Serializable

it register current class to type list.

export enum SerializableMode {
    IGNORE = 0,
    TO_PLAIN_ONLY = 1,
    TO_CLASS_ONLY = 2,
    TO_PLAIN_AND_CLASS = TO_PLAIN_ONLY | TO_CLASS_ONLY,
}

export interface SerializableOptions {
    // you can ignore all properties by setting mode on serlization or deserialization. 
    mode: SerializableMode;
    // you can customized the serialized and deserialized by toClass or toPlain.
    toClass?: (value: any, context: SerializableContext) => Promise<any> | any;
    toPlain?: (value: any, context: SerializableContext) => Promise<any> | any;
    // it will be called on serlization or deserialization, you can do anything else on these call back functions.
    onSerialized?: (instance: SerializableDataType, context: SerializableContext) => Promise<void> | void;
    onDeserialized?: (instance: any, context: SerializableContext) => Promise<void> | void;
}

@Serializable()
class MyClass {}

SerializeField

you can customized any filed by SerializeField, or just tell serializer serialize any properties.

export interface SerializableFieldOptions {
    mode: SerializableMode;
    toPlain: (param: any, context: SerializableContext) => Promise<any> | any;
    toClass: (param: any, context: SerializableContext) => Promise<any> | any;
    onSerialized: (instance: SerializableDataType, context: SerializableContext) => Promise<void> | void;
    onDeserialized?: (instance: any, context: SerializableContext) => Promise<void> | void;
}

@Serializable()
class ClassUnderTest {
    // it can serialize accesser as property by SerializeField
    @SerializeField()
    get test() {
        return 'test';
    }
    set test(value: string) {
        this.testValue = value;
    }
}

Ignore

you can ignore any property by Ignore

@Serializable()
class ClassUnderTest {
    // ignore any property
    @Ignore()
    id: string = 'test';
}

SerializeParam

you can set the default param by SerializeParam

export interface SerializableParamOptions<T> {
    toClass: (value: any, context: SerializableContext) => Promise<T> | T;
    toPlain: (value: T, context: SerializableContext) => Promise<any> | any;
    onSerialized: (instance: SerializableDataType, context: SerializableContext) => Promise<void> | void;
    onDeserialized?: (instance: any, context: SerializableContext) => Promise<void> | void;
}

@Serializable()
class ParentUnderTest {
    id: string = 'parent';
    child: ChildUnderTest;
    constructor() {
        this.child = new ChildUnderTest(this);
    }
}
@Serializable()
class ChildUnderTest {
    id: string = 'child';
    @SerializeField({ mode: SerializableMode.IGNORE })
    parent: ParentUnderTest;
    constructor(
    	// it will export object's 'parent' for default. And you can customlized by options.
        @SerializeParam(ctx => ctx.instance.parent, {})
        parent: ParentUnderTest
         // You can also set a value for default
        @SerializeParam(3)
    	num: number
    ) {
        this.parent = parent;
    }
}