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

serialzr

v1.5.1

Published

JS library for serializing and deserializing complex objects into JSON and back.

Downloads

183

Readme

Serializer

JS library for serializing and deserializing complex objects into JSON and back.

NPM Version GitHub top language GitHub Actions Workflow Status Codecov

Features

  • two-way serialization / deserialization without specifying target type - thanks to @type property

  • defining exposed / excluded properties via groups or graph

  • defining custom serialization / deserialization functions (per type or per property)

  • built-in support for array of objects and Record<string, T> maps

  • ESM

  • zero dependencies

  • full TypeScript support

  • covered with tests

NPM package

yarn add serialzr

Detailes features

1. Property Exclusion and Exposure

You can control which properties are included in the serialized output and which are not.
This can be done using the @Srlz.Expose() and @Srlz.Exclude() decorators.

class Foo
{
    @Srlz.Expose()
    public exposedProperty : string = 'exposed';
    
    @Srlz.Exclude()
    public excludedProperty : string = 'excluded';
}

const plain = serializer.toPlain(new Foo());
// { exposedProperty: 'exposed' }

2. Grouping

You can specify groups for properties, allowing you to control the serialization and deserialization process based on these groups.

class Foo
{
    @Srlz.Expose([ 'group1' ])
    public property1 : string = 'property1';
    
    @Srlz.Expose([ 'group2' ])
    public property2 : string = 'property2';
}

const plain = serializer.toPlain(new Foo(), {
    groups: [ 'group1' ]
});
// { property1: 'property1' }

3. Auto Groups

The library allows you to automatically add groups based on certain conditions.

@Srlz.AutoGroup('detailed', (obj, ctx) => ctx.detailedEntries?.includes(obj.id))
class Entry
{
    @Srlz.Id()
    public id : number = 1;
    
    @Srlz.Expose([ 'detailed' ])
    public stats : string = 'stats';
}

const plain = serializer.toPlain(new User(), {
    ctxData: {
        detailedEntries: [ 1, 2 ]
    }
});
// { id: 1, stats: 'stats' }

4. Graph Serialization

The library supports graph serialization, allowing you to control how nested objects are serialized.

@Srlz.Type('book')
class Book
{
    @Srlz.Id()
    public id : number = 5;
    
    @Srlz.Expose([ 'public' ])
    public name : string = 'Noname';
    
    public constructor (data : Partial<Book> = {})
    {
        Object.assign(this, data);
    }
}

@Srlz.Type('author')
class Author
{
    @Srlz.Id()
    public id : number = 5;
    
    @Srlz.Expose([ 'public' ])
    public name : string = 'John Doe';
    
    @Srlz.Expose([ 'public' ])
    public age : number = 18;
    
    @Srlz.Type({ arrayOf: () => Book })
    public books : Book[] = [
        new Book({ id: 8, name: 'Book 1' }),
        new Book({ id: 9, name: 'Book 2' }),
    ];
    
    @Srlz.Expose([ 'owner' ]) // only owner can see this
    @Srlz.Type({ recordOf: () => Book })
    public aliasedBooks : Record<string, Book> = {
        a: new Book({ id: 10, name: 'Book 3' }),
    };
    
    @Srlz.Exclude() // excluded even if default strategy is to include
    public secret : number = 12345;
    
    public constructor (data : Partial<Author> = {})
    {
        Object.assign(this, data);
    }
}

const plain = serializer.toPlain(new Author(), {
    graph: {
        $default: false,
        id: true,
        name: true,
        books: '**',
        aliasedBooks: {
            id: true,
            name: true,
        }
    }
});
// { 
//      id: 5, 
//      name: 'John Doe', 
//      books: [ 
//          { id: 8, name: 'Book 1' },
//          { id: 9, name: 'Book 2' } 
//      ],
//      aliasedBooks: { 
//          a: { id: 10, name: 'Book 3' }
//      } 
// }

5. Custom Serialization and Deserialization Strategies

You can define custom strategies for serializing and deserializing properties.

@Srlz.Transformer({
    toPlain: (obj) => obj.text.toLowerCase(),
    toClass: (plain) => new Tag({ text: plain.toLowerCase() }),
})
class Tag
{
    public text : string = 'tag';
    
    public constructor (data : Partial<Tag> = {})
    {
        Object.assign(this, data);
    }
}

Refrence

1. Class decorator @Srlz.Type()

As class decorator, it marks the class as a serializable type.

function Type (typeName : string)
function Type (typeDef : {
    name? : string,
    idProperty? : string,
})

2. Class decorator @Srlz.AutoGroup()

Defines a group that is automatically added to the object based on the condition.

function AutoGroup (
    groupName : string, // group name
    condition : (
        obj : any, // currently serialized object
        ctx : any // context data (passed to toPlain and toClass methods under ctxData key)
    ) => boolean
)

3. Class decorator @Srlz.Transformer()

Defines custom serialization and deserialization strategies for the class.

type TransformerFnParams = {
    direction : Direction,
    type : any,
    options? : SerializationOptions.Base<T> | any,
    context? : SerializationContext.Base<T> | any,
}
function Transformer (
    def : {
        toPlain : (obj : any, params : TransformerFnParams) => any,     // serialization function (before exposure calculation)
        toClass : (plain : any, params : TransformerFnParams) => any,   // deserialization function (before exposure calculation)
    }
)
function Transformer (
    def : {
        toPlain : {
            before? : (obj : any, params : TransformerFnParams) => any, // before exposure calculation
            after? : (plain : any, params : TransformerFnParams) => any, // after exposure calculation
        }
        toClass : {
            before? : (plain : any, params : TransformerFnParams) => any, // before exposure calculation
            after? : (obj : any, params : TransformerFnParams) => any, // after exposure calculation
        }
    }
)

4. Property decorator @Srlz.Id()

Marks the property as an identifier.

5. Property decorator @Srlz.Expose()

Marks the property as exposed.

function Expose () // exposes property by default
function Expose (groups : string[]) // exposes property only for specified groups
function Expose (def : { // complex configuration
    // modifiers
    mode? : boolean = true, // true - expose, false - exclude
    deeply? : boolean, // expose deeply
    
    // conditions
    all? : string[], // matched if all groups are present
    any? : string[], // matched if any group is present
    notAll? : string[], // matched if no all groups are present
    notAny? : string[], // matched if none of groups is present
}) 

6. Property decorator @Srlz.Exclude()

Marks the property as excluded.
Sample usage is the same as for @Srlz.Expose().

7. Property decorator @Srlz.Type()

Defines the type of the property.
It is required to specify the type of the property if it is not a primitive type.

function Type (type : () => ClassConstructor) // for single object
function Type (def : {
    type : () => ClassConstructor, // for single object
    arrayOf : () => ClassConstructor, // for array of objects
    recordOf : () => ClassConstructor, // for record of objects
})

8. Property decorator @Srlz.Transformer()

Defines custom serialization and deserialization strategies for the property.
Usage is the same as for @Srlz.Transformer() class decorator.

9. Property decorator @Srlz.Computed()

Defines a computed property.

type GetterFn = (args : {
    value : any,                    // current property value
    parent : any,                   // parent object
    params : TransformerFnParams,
}) => any;
function Computed (getterFn : GetterFn)

10. Property decorator @Srlz.ComputedByGroup()

Defines a computed property.

function ComputedByGroup (
    group : string,                         // group name to match
    ifIncludes : GetterFn = () => true,     // getter function to use if group is included
    ifNotIncludes : GetterFn = () => false, // getter function to use if group is not included
)