or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-serialization.mdfield-configuration.mdglobal-configuration.mdindex.mdundefined-parameters.md

global-configuration.mddocs/

0

# Global Configuration

1

2

Package-wide settings for custom encoders, decoders, and marshmallow fields that apply across all dataclasses unless overridden at the field level. Global configuration provides a centralized way to define type-specific serialization behavior.

3

4

## Capabilities

5

6

### Global Configuration Object

7

8

The `global_config` object provides package-wide settings that affect all dataclass serialization unless overridden.

9

10

```python { .api }

11

class _GlobalConfig:

12

"""

13

Global configuration singleton for package-wide serialization settings.

14

"""

15

encoders: Dict[Union[type, Optional[type]], Callable]

16

decoders: Dict[Union[type, Optional[type]], Callable]

17

mm_fields: Dict[Union[type, Optional[type]], marshmallow.fields.Field]

18

19

global_config: _GlobalConfig

20

```

21

22

The global configuration object contains three main dictionaries:

23

24

- **encoders**: Maps types to functions that convert Python values to JSON-serializable values

25

- **decoders**: Maps types to functions that convert JSON values back to Python values

26

- **mm_fields**: Maps types to marshmallow Field instances for validation and transformation

27

28

## Global Encoder Configuration

29

30

Register custom encoders for specific types that will be used across all dataclasses.

31

32

```python { .api }

33

# Encoder function signature

34

EncoderFunc = Callable[[Any], Any] # Python value -> JSON-serializable value

35

```

36

37

Usage example:

38

39

```python

40

from dataclasses import dataclass

41

from dataclasses_json import dataclass_json, global_config

42

from datetime import date, datetime

43

from decimal import Decimal

44

import uuid

45

46

# Register global encoders

47

global_config.encoders[date] = lambda d: d.isoformat()

48

global_config.encoders[datetime] = lambda dt: dt.isoformat()

49

global_config.encoders[Decimal] = str

50

global_config.encoders[uuid.UUID] = str

51

52

@dataclass_json

53

@dataclass

54

class Document:

55

id: uuid.UUID

56

title: str

57

created_date: date

58

modified_time: datetime

59

price: Decimal

60

61

# All instances automatically use global encoders

62

doc = Document(

63

id=uuid.uuid4(),

64

title="Sample Document",

65

created_date=date.today(),

66

modified_time=datetime.now(),

67

price=Decimal("19.99")

68

)

69

70

json_str = doc.to_json()

71

# Uses global encoders for UUID, date, datetime, and Decimal

72

```

73

74

## Global Decoder Configuration

75

76

Register custom decoders for converting JSON values back to Python types.

77

78

```python { .api }

79

# Decoder function signature

80

DecoderFunc = Callable[[Any], Any] # JSON value -> Python value

81

```

82

83

Usage example:

84

85

```python

86

from datetime import date, datetime

87

from decimal import Decimal

88

import uuid

89

90

# Register global decoders

91

global_config.decoders[date] = lambda s: datetime.fromisoformat(s).date()

92

global_config.decoders[datetime] = datetime.fromisoformat

93

global_config.decoders[Decimal] = Decimal

94

global_config.decoders[uuid.UUID] = uuid.UUID

95

96

# Now all dataclasses can deserialize these types automatically

97

json_data = '''{

98

"id": "123e4567-e89b-12d3-a456-426614174000",

99

"title": "Sample Document",

100

"created_date": "2023-12-01",

101

"modified_time": "2023-12-01T10:30:00",

102

"price": "19.99"

103

}'''

104

105

doc = Document.from_json(json_data)

106

# Automatically converts strings back to proper types

107

```

108

109

## Global Marshmallow Field Configuration

110

111

Register marshmallow fields for types that require validation or complex transformation.

112

113

```python { .api }

114

from marshmallow import fields

115

116

# Common marshmallow field types

117

Field = fields.Field

118

```

119

120

Usage example:

121

122

```python

123

from marshmallow import fields

124

from datetime import datetime

125

from decimal import Decimal

126

127

# Register global marshmallow fields

128

global_config.mm_fields[datetime] = fields.DateTime(format='iso')

129

global_config.mm_fields[Decimal] = fields.Decimal(places=2, rounding='ROUND_HALF_UP')

130

global_config.mm_fields[str] = fields.String(validate=lambda x: len(x.strip()) > 0)

131

132

@dataclass_json

133

@dataclass

134

class Order:

135

timestamp: datetime

136

amount: Decimal

137

description: str

138

139

# Schema validation uses global mm_fields

140

schema = Order.schema()

141

142

# This will validate using global field definitions

143

try:

144

order = schema.loads('{"timestamp": "2023-12-01T10:30:00", "amount": "19.999", "description": ""}')

145

except ValidationError as e:

146

print("Validation failed:", e) # Empty description fails validation

147

```

148

149

## Configuration Priority

150

151

Configuration follows a clear precedence hierarchy:

152

153

1. **Field-level configuration** (highest priority)

154

2. **Global configuration**

155

3. **Library defaults** (lowest priority)

156

157

Example demonstrating precedence:

158

159

```python

160

from dataclasses import dataclass, field

161

from dataclasses_json import dataclass_json, config, global_config

162

from datetime import datetime

163

164

# Global configuration

165

global_config.encoders[datetime] = lambda dt: dt.strftime('%Y-%m-%d')

166

167

@dataclass_json

168

@dataclass

169

class Event:

170

# Uses global encoder (YYYY-MM-DD format)

171

start_time: datetime

172

173

# Field-level config overrides global (ISO format)

174

end_time: datetime = field(metadata=config(

175

encoder=lambda dt: dt.isoformat()

176

))

177

178

event = Event(datetime.now(), datetime.now())

179

json_str = event.to_json()

180

# start_time uses global encoder, end_time uses field-level encoder

181

```

182

183

## Advanced Global Configuration Patterns

184

185

### Type Hierarchy Configuration

186

187

Configure encoders for base classes that apply to all subclasses:

188

189

```python

190

from abc import ABC, abstractmethod

191

192

class SerializableEntity(ABC):

193

@abstractmethod

194

def to_dict(self):

195

pass

196

197

# Global encoder for all SerializableEntity subclasses

198

global_config.encoders[SerializableEntity] = lambda obj: obj.to_dict()

199

200

class User(SerializableEntity):

201

def __init__(self, name: str):

202

self.name = name

203

204

def to_dict(self):

205

return {"name": self.name}

206

207

@dataclass_json

208

@dataclass

209

class Document:

210

author: User # Uses global SerializableEntity encoder

211

title: str

212

```

213

214

### Optional Type Configuration

215

216

Handle Optional types explicitly:

217

218

```python

219

from typing import Optional

220

from datetime import datetime

221

222

# Configure for Optional[datetime]

223

global_config.encoders[Optional[datetime]] = lambda dt: dt.isoformat() if dt else None

224

global_config.decoders[Optional[datetime]] = lambda s: datetime.fromisoformat(s) if s else None

225

226

@dataclass_json

227

@dataclass

228

class Task:

229

name: str

230

due_date: Optional[datetime] = None # Uses Optional[datetime] configuration

231

```

232

233

### Environment-Based Configuration

234

235

Configure based on runtime environment:

236

237

```python

238

import os

239

from datetime import datetime

240

241

# Development vs Production encoders

242

if os.getenv('ENV') == 'development':

243

# Verbose format for debugging

244

global_config.encoders[datetime] = lambda dt: {

245

'timestamp': dt.isoformat(),

246

'readable': dt.strftime('%Y-%m-%d %H:%M:%S'),

247

'timezone': str(dt.tzinfo)

248

}

249

else:

250

# Compact format for production

251

global_config.encoders[datetime] = lambda dt: dt.timestamp()

252

```

253

254

### Configuration Validation

255

256

Validate global configuration at startup:

257

258

```python

259

def validate_global_config():

260

"""Validate that all global encoders have corresponding decoders."""

261

encoder_types = set(global_config.encoders.keys())

262

decoder_types = set(global_config.decoders.keys())

263

264

missing_decoders = encoder_types - decoder_types

265

if missing_decoders:

266

raise ValueError(f"Missing decoders for types: {missing_decoders}")

267

268

# Call during application initialization

269

validate_global_config()

270

```

271

272

### Configuration Backup and Restore

273

274

Save and restore configuration state:

275

276

```python

277

def backup_global_config():

278

"""Create a backup of current global configuration."""

279

return {

280

'encoders': global_config.encoders.copy(),

281

'decoders': global_config.decoders.copy(),

282

'mm_fields': global_config.mm_fields.copy()

283

}

284

285

def restore_global_config(backup):

286

"""Restore global configuration from backup."""

287

global_config.encoders.clear()

288

global_config.encoders.update(backup['encoders'])

289

global_config.decoders.clear()

290

global_config.decoders.update(backup['decoders'])

291

global_config.mm_fields.clear()

292

global_config.mm_fields.update(backup['mm_fields'])

293

294

# Usage in tests

295

def test_with_custom_config():

296

backup = backup_global_config()

297

try:

298

# Modify global config for test

299

global_config.encoders[str] = lambda s: s.upper()

300

# ... run test ...

301

finally:

302

restore_global_config(backup)

303

```

304

305

## Performance Considerations

306

307

Global configuration lookups are performed for every field serialization. For optimal performance:

308

309

- Keep global configuration minimal and focused on frequently used types

310

- Use field-level configuration for one-off customizations

311

- Consider caching for expensive encoder/decoder operations

312

313

```python

314

from functools import lru_cache

315

316

# Cache expensive transformations

317

@lru_cache(maxsize=1000)

318

def expensive_encoder(value):

319

# Complex transformation logic

320

return transformed_value

321

322

global_config.encoders[ComplexType] = expensive_encoder

323

```