marshalers

package
v1.5.21 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 16, 2026 License: AGPL-3.0 Imports: 16 Imported by: 0

README

DynamORM Custom Marshalers

This package provides custom marshaling and unmarshaling functionality for complex data types in DynamoDB.

Features

Core Interfaces
  • Marshaler: Interface for custom DynamoDB marshaling
  • Unmarshaler: Interface for custom DynamoDB unmarshaling
  • MarshalUnmarshaler: Combined interface for both operations
Built-in Custom Types
PreciseTime

Time values with configurable precision (second, millisecond, microsecond, nanosecond).

// Create precise time with millisecond precision
pt := marshalers.NewPreciseTime(time.Now(), time.Millisecond)

// Create with current time
pt := marshalers.NewPreciseTimeNow(time.Second)
Money

Monetary values with currency information using decimal precision.

// Create from decimal
money := marshalers.NewMoney(decimal.NewFromFloat(123.45), "USD")

// Create from float
money := marshalers.NewMoneyFromFloat(123.45, "USD")

// Create from string
money, err := marshalers.NewMoneyFromString("123.45", "USD")

// Arithmetic operations
sum, err := money1.Add(money2)
diff, err := money1.Sub(money2)
EncryptedString

Encrypted string values using AES-GCM encryption.

// Setup encryption
encryptor, err := marshalers.NewAESEncryptor() // Uses DYNAMODB_ENCRYPTION_KEY env var
// Or with custom key
key, _ := marshalers.GenerateEncryptionKey()
encryptor, err := marshalers.NewAESEncryptorWithKey(key)

// Create encrypted string
encrypted := marshalers.NewEncryptedString("secret", encryptor)
JSONField

Store arbitrary JSON data in DynamoDB.

// Store any data as JSON
data := map[string]interface{}{
    "name": "John",
    "age": 30,
}
field := marshalers.NewJSONField(data)

// Unmarshal into specific type
var user User
err := field.UnmarshalInto(&user)
StringSet

DynamoDB string set with additional functionality.

// Create string set
ss := marshalers.NewStringSet("a", "b", "c")

// Operations
ss.Add("d", "e")
ss.Remove("b")
contains := ss.Contains("a")
size := ss.Size()

Usage Examples

Model Integration
type User struct {
    ID          string                    `dynamodbav:"pk"`
    Balance     marshalers.Money          `dynamodbav:"balance"`
    LastLogin   marshalers.PreciseTime    `dynamodbav:"last_login"`
    APIKey      marshalers.EncryptedString `dynamodbav:"api_key"`
    Preferences marshalers.JSONField      `dynamodbav:"preferences"`
    Tags        marshalers.StringSet      `dynamodbav:"tags"`
}
Environment Setup

For encrypted fields, set the encryption key:

export DYNAMODB_ENCRYPTION_KEY="<base64-encoded-32-byte-key>"

Generate a key:

key, err := marshalers.GenerateEncryptionKey()
keyBase64 := marshalers.EncodeEncryptionKey(key)

Testing

All custom marshalers include comprehensive tests covering:

  • Marshal/unmarshal round trips
  • Error handling
  • Edge cases
  • Type validation
  • Encryption/decryption

Run tests:

go test ./pkg/storage/dynamorm/marshalers/ -v

Security Considerations

  • EncryptedString: Uses AES-256-GCM for authenticated encryption
  • Money: Decimal precision prevents floating-point errors
  • JSONField: Sanitizes JSON input/output
  • All types validate input and handle edge cases gracefully

Documentation

Overview

Package marshalers provides custom DynamoDB marshaling utilities with encryption support for sensitive data using DynamORM.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func EncodeEncryptionKey

func EncodeEncryptionKey(key []byte) string

EncodeEncryptionKey encodes an encryption key as base64

func GenerateEncryptionKey

func GenerateEncryptionKey() ([]byte, error)

GenerateEncryptionKey creates an encryption key for testing

Types

type AESEncryptor

type AESEncryptor struct {
	// contains filtered or unexported fields
}

AESEncryptor implements AES encryption

func NewAESEncryptor

func NewAESEncryptor() (*AESEncryptor, error)

NewAESEncryptor creates a new AES encryptor from centralized config

func NewAESEncryptorWithKey

func NewAESEncryptorWithKey(key []byte) (*AESEncryptor, error)

NewAESEncryptorWithKey creates a new AES encryptor with provided key

func (*AESEncryptor) Decrypt

func (e *AESEncryptor) Decrypt(ciphertext []byte) ([]byte, error)

Decrypt decrypts ciphertext using AES-GCM

func (*AESEncryptor) Encrypt

func (e *AESEncryptor) Encrypt(plaintext []byte) ([]byte, error)

Encrypt encrypts plaintext using AES-GCM

type EncryptedString

type EncryptedString struct {
	Value string
	// contains filtered or unexported fields
}

EncryptedString represents an encrypted string value

func NewEncryptedString

func NewEncryptedString(value string, encryptor Encryptor) EncryptedString

NewEncryptedString creates a new EncryptedString

func (EncryptedString) MarshalDynamORM

func (es EncryptedString) MarshalDynamORM() (interface{}, error)

MarshalDynamORM implements the Marshaler interface for EncryptedString

func (*EncryptedString) SetEncryptor

func (es *EncryptedString) SetEncryptor(encryptor Encryptor)

SetEncryptor sets the encryptor for the EncryptedString

func (EncryptedString) String

func (es EncryptedString) String() string

String returns the decrypted value (be careful with logging!)

func (*EncryptedString) UnmarshalDynamORM

func (es *EncryptedString) UnmarshalDynamORM(data interface{}) error

UnmarshalDynamORM implements the Unmarshaler interface for EncryptedString

type Encryptor

type Encryptor interface {
	Encrypt(plaintext []byte) ([]byte, error)
	Decrypt(ciphertext []byte) ([]byte, error)
}

Encryptor interface for encryption operations

type JSONField

type JSONField struct {
	Data any
}

JSONField represents a field that stores arbitrary JSON data

func NewJSONField

func NewJSONField(data any) JSONField

NewJSONField creates a new JSONField

func (JSONField) IsNull

func (jf JSONField) IsNull() bool

IsNull returns true if the JSON field contains null data

func (JSONField) MarshalDynamORM

func (jf JSONField) MarshalDynamORM() (interface{}, error)

MarshalDynamORM implements the Marshaler interface for JSONField

func (JSONField) String

func (jf JSONField) String() string

String returns a string representation of the JSON data

func (*JSONField) UnmarshalDynamORM

func (jf *JSONField) UnmarshalDynamORM(data interface{}) error

UnmarshalDynamORM implements the Unmarshaler interface for JSONField

func (JSONField) UnmarshalInto

func (jf JSONField) UnmarshalInto(target any) error

UnmarshalInto unmarshals the JSON data into a specific type

type KMSEncryptor

type KMSEncryptor struct {
	// contains filtered or unexported fields
}

KMSEncryptor implements encryption using AWS KMS

func NewKMSEncryptor

func NewKMSEncryptor(keyID string) (*KMSEncryptor, error)

NewKMSEncryptor creates a new KMS encryptor

func (*KMSEncryptor) Decrypt

func (e *KMSEncryptor) Decrypt(ciphertext []byte) ([]byte, error)

Decrypt decrypts ciphertext using KMS

func (*KMSEncryptor) DecryptFromBase64

func (e *KMSEncryptor) DecryptFromBase64(encoded string) ([]byte, error)

DecryptFromBase64 decrypts from base64-encoded ciphertext

func (*KMSEncryptor) Encrypt

func (e *KMSEncryptor) Encrypt(plaintext []byte) ([]byte, error)

Encrypt encrypts plaintext using KMS

func (*KMSEncryptor) EncryptToBase64

func (e *KMSEncryptor) EncryptToBase64(plaintext []byte) (string, error)

EncryptToBase64 encrypts and returns base64-encoded ciphertext

type MarshalUnmarshaler

type MarshalUnmarshaler interface {
	Marshaler
	Unmarshaler
}

MarshalUnmarshaler combines both interfaces

type Marshaler

type Marshaler interface {
	MarshalDynamORM() (interface{}, error)
}

Marshaler interface for custom DynamORM marshaling

type Money

type Money struct {
	Amount   decimal.Decimal `json:"amount"`
	Currency string          `json:"currency"`
}

Money represents monetary values with currency information

func NewMoney

func NewMoney(amount decimal.Decimal, currency string) Money

NewMoney creates a new Money instance

func NewMoneyFromFloat

func NewMoneyFromFloat(amount float64, currency string) Money

NewMoneyFromFloat creates a new Money instance from a float64

func NewMoneyFromString

func NewMoneyFromString(amount, currency string) (Money, error)

NewMoneyFromString creates a new Money instance from a string

func (Money) Add

func (m Money) Add(other Money) (Money, error)

Add adds another Money value (must be same currency)

func (Money) IsZero

func (m Money) IsZero() bool

IsZero returns true if the money amount is zero

func (Money) MarshalDynamORM

func (m Money) MarshalDynamORM() (interface{}, error)

MarshalDynamORM implements the Marshaler interface for Money

func (Money) String

func (m Money) String() string

String returns a string representation of Money

func (Money) Sub

func (m Money) Sub(other Money) (Money, error)

Sub subtracts another Money value (must be same currency)

func (*Money) UnmarshalDynamORM

func (m *Money) UnmarshalDynamORM(data interface{}) error

UnmarshalDynamORM implements the Unmarshaler interface for Money

type PreciseTime

type PreciseTime struct {
	time.Time
	Precision time.Duration
}

PreciseTime represents a time with configurable precision

func NewPreciseTime

func NewPreciseTime(t time.Time, precision time.Duration) PreciseTime

NewPreciseTime creates a new PreciseTime with the specified precision

func NewPreciseTimeNow

func NewPreciseTimeNow(precision time.Duration) PreciseTime

NewPreciseTimeNow creates a new PreciseTime with the current time and specified precision

func (PreciseTime) MarshalDynamORM

func (pt PreciseTime) MarshalDynamORM() (interface{}, error)

MarshalDynamORM implements the Marshaler interface for PreciseTime

func (PreciseTime) String

func (pt PreciseTime) String() string

String returns a string representation of PreciseTime

func (*PreciseTime) UnmarshalDynamORM

func (pt *PreciseTime) UnmarshalDynamORM(data interface{}) error

UnmarshalDynamORM implements the Unmarshaler interface for PreciseTime

type StringSet

type StringSet struct {
	Values []string
}

StringSet represents a DynamoDB string set with additional functionality

func NewStringSet

func NewStringSet(values ...string) StringSet

NewStringSet creates a new StringSet

func (*StringSet) Add

func (ss *StringSet) Add(values ...string)

Add adds values to the string set

func (StringSet) Contains

func (ss StringSet) Contains(value string) bool

Contains checks if the set contains a value

func (StringSet) IsEmpty

func (ss StringSet) IsEmpty() bool

IsEmpty returns true if the set is empty

func (StringSet) MarshalDynamORM

func (ss StringSet) MarshalDynamORM() (interface{}, error)

MarshalDynamORM implements the Marshaler interface for StringSet

func (*StringSet) Remove

func (ss *StringSet) Remove(values ...string)

Remove removes values from the string set

func (StringSet) Size

func (ss StringSet) Size() int

Size returns the number of elements in the set

func (StringSet) String

func (ss StringSet) String() string

String returns a string representation of the set

func (StringSet) ToSlice

func (ss StringSet) ToSlice() []string

ToSlice returns the values as a slice

func (*StringSet) UnmarshalDynamORM

func (ss *StringSet) UnmarshalDynamORM(data interface{}) error

UnmarshalDynamORM implements the Unmarshaler interface for StringSet

type Unmarshaler

type Unmarshaler interface {
	UnmarshalDynamORM(interface{}) error
}

Unmarshaler interface for custom DynamORM unmarshaling

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL