json-accelerator

repository·main·Indexed 19 days ago

https://github.com/elysiajs/json-accelerator

A high-performance JSON stringification library that uses TypeBox or OpenAPI schemas to pre-generate optimized serialization functions. It provides the createAccelerator function to generate specialized string templates that are faster than standard JSON.stringify. The library does not perform type validation and supports configurable unsafe character handling via 'auto', 'manual', and 'throw' modes, as well as schema reference resolution through a definitions object.

Tokens
2.2K
Snippets
7
Records
8
Agent score
18%

What's inside json-accelerator

  1. Optimize performance with manual sanitization

    main

    In controlled environments like RESTful APIs, most fields are known to be safe. You can improve performance by setting the global unsafe option to 'manual' and explicitly marking only uncontrolled user-submitted fields for sanitization in the schema using { sanitize: true }.

    When a field is marked with sanitize: true, the encoder will sanitize that specific string and continue encoding regardless of the global unsafe configuration.

    import { Type as t } from '@sinclair/typebox'
    import { createAccelerator } from 'json-accelerator'
    
    const shape = t.Object({
    	name: t.String(),
    	id: t.Number(),
    	unknown: t.String({ sanitize: true }) // Explicitly mark as needing sanitization
    })
    
    const value = {
    	id: 0,
    	name: 'saltyaom',
    	unknown: `hello\nworld`
    } satisfies typeof shape.static
    
    // Set to 'manual' to skip automatic sanitization on all other fields
    const encode = createAccelerator(shape, {
    	sanitize: 'manual'
    })
    
    console.log(encode(value)) // {"id":0,"name":"saltyaom","unknown":"hello\\nworld"}
  2. Validate input before using the accelerator

    main

    Because createAccelerator expects the schema to be always correct, use TypeCompiler to guard your inputs. This prevents errors or unexpected coercion when the input shape does not match the schema.

    import { Type as t } from '@sinclair/typebox'
    import { TypeCompiler } from '@sinclair/typebox/compiler'
    import { createAccelerator } from 'json-accelerator'
    
    const shape = t.Object({
    	name: t.String(),
    	id: t.Number()
    })
    
    const value = {
    	id: 0,
    	name: 'saltyaom'
    }
    
    const guard = TypeCompiler.Compile(shape)
    const encode = createAccelerator(shape)
    
    if (guard.Check(value)) encode(value)
  3. Configure unsafe character handling with Options

    main

    You can pass an options object as the second argument to createAccelerator to control how the encoder handles unsafe characters in string fields via the unsafe key.

    unsafe options:

    • 'auto' (default): Automatically sanitizes the string and continues encoding.
    • 'manual': Ignores unsafe characters. This mode is intended for use when you specify certain fields to be sanitized manually via the schema to improve performance.
    • 'throw': Throws an error if an unsafe character is encountered.
    createAccelerator(shape, {
    	unsafe: 'throw'
    })
  4. Use createAccelerator to speed up JSON stringification

    main

    The createAccelerator function generates a high-performance serialization function based on a provided TypeBox or OpenAPI schema. This is significantly faster than standard JSON.stringify because the serialization logic is pre-generated for the specific shape of your data.

    Important Caveat: The library does not perform type validation. It assumes the input data strictly adheres to the schema. To ensure safety, you should validate your data using a TypeBox compiler (like TypeCompiler.Compile) before passing it to the accelerator.

    import { Type as t } from '@sinclair/typebox'
    import { createAccelerator } from 'json-accelerator'
    
    const shape = t.Object({
    	name: t.String(),
    	id: t.Number()
    })
    
    const value = {
    	id: 0,
    	name: 'saltyaom'
    } satisfies typeof shape.static
    
    const encode = createAccelerator(shape)
    
    console.log(encode(value)) // {"id":0,"name":"saltyaom"}
  5. Configure string sanitization in createAccelerator

    main

    The sanitize option controls how the generated encoder handles potentially unsafe characters (like newlines, quotes, or tabs) in string fields. This is crucial for preventing malformed JSON output.

    | Value | Behavior | |---|---|'auto' (default) | Uses JSON.stringify logic to escape characters only when necessary. If the schema is marked as trusted, it skips escaping for maximum speed. |'manual' | Does no escaping. Use this only if you are certain the input strings are already sanitized. |'throw' | Checks for unsafe characters using a regex; if found, it throws an error during execution. |

    Note: The 'auto' mode is optimized to minimize the performance overhead of slice(1, -1) operations typically used when wrapping JSON.stringify results.

  6. Create an optimized JSON encoder with createAccelerator

    main

    Use createAccelerator to generate a highly optimized function that converts data matching a TypeBox schema into a JSON string. Instead of using the standard JSON.stringify, this function generates a specialized, high-performance string template specifically tailored to your schema's structure.

    Usage

    1. Define your schema using @sinclair/typebox.
    2. Pass the schema to createAccelerator.
    3. Use the returned function to encode your data.

    Configuration Options

    When calling createAccelerator, you can provide an options object:

    • sanitize: Determines how to handle unsafe characters in strings. Defaults to 'auto'.
      • 'auto': Automatically detects if sanitization is needed and uses JSON.stringify logic to escape characters.
      • 'manual': Assumes the input is already safe; no extra processing is performed.
      • 'throw': Throws an error if invalid characters are detected.
    • definitions: A record of TAnySchema objects used to resolve $ref pointers within your schema.

    Note: If you use sanitize: 'auto', the encoder may use JSON.stringify internally for specific string fields to ensure safety, but it optimizes the rest of the structure.

    import { Type } from '@sinclair/typebox'
    import { createAccelerator } from 'json-accelerator'
    
    const UserSchema = Type.Object({
      id: Type.Number(),
      name: Type.String(),
      email: Type.Optional(Type.String())
    })
    
    // Create the optimized encoder
    const encode = createAccelerator(UserSchema)
    
    // Use it to transform data to a JSON string
    const jsonString = encode({
      id: 1,
      name: 'John Doe'
    })
    
    console.log(jsonString) // '{"id":1,"name":"John Doe"}'
  7. Resolve schema references using definitions

    main

    If your TypeBox schema uses $ref to point to definitions (e.g., via Type.Reference), you must provide those definitions to createAccelerator so it can resolve them during code generation.

    Pass a definitions object where keys are the reference names and values are the corresponding TAnySchema objects.

    import { Type } from '@sinclair/typebox'
    import { createAccelerator }
    
    const SharedSchema = Type.Object({ id: Type.String() })
    
    const RootSchema = Type.Object({
      user: Type.Ref('user')
    })
    
    // Provide the definitions so the accelerator can find 'user'
    const encode = createAccelerator(RootSchema, {
      definitions: {
        user: SharedSchema
      }
    })