or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

tessl/pypi-json5

A Python implementation of the JSON5 data format.

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
pypipkg:pypi/json5@0.12.x

To install, run

npx @tessl/cli install tessl/pypi-json5@0.12.0

0

# JSON5

1

2

A Python implementation of the JSON5 data format. JSON5 extends standard JSON with JavaScript-style features including single and multi-line comments, unquoted object keys for valid ECMAScript identifiers, trailing commas in objects and arrays, single-quoted strings, and multi-line string literals. This library mirrors the standard Python JSON API for ease of use.

3

4

## Package Information

5

6

- **Package Name**: json5

7

- **Language**: Python

8

- **Installation**: `pip install json5`

9

10

## Core Imports

11

12

```python

13

import json5

14

```

15

16

All functions are available at the top level:

17

18

```python

19

from json5 import load, loads, dump, dumps, parse, JSON5Encoder, QuoteStyle

20

```

21

22

## Basic Usage

23

24

```python

25

import json5

26

27

# Parse JSON5 string

28

data = json5.loads('''

29

{

30

// JavaScript-style comments

31

unquoted: "keys are allowed",

32

'single': 'quotes work too',

33

"trailing": "commas are ok",

34

}

35

''')

36

37

# Serialize Python object to JSON5

38

obj = {"name": "example", "values": [1, 2, 3]}

39

json5_string = json5.dumps(obj, indent=2, trailing_commas=True)

40

print(json5_string)

41

# Output:

42

# {

43

# name: 'example',

44

# values: [

45

# 1,

46

# 2,

47

# 3,

48

# ],

49

# }

50

51

# Parse from file

52

with open('config.json5', 'r') as f:

53

config = json5.load(f)

54

55

# Write to file

56

with open('output.json5', 'w') as f:

57

json5.dump(data, f, indent=2, quote_keys=False)

58

```

59

60

## Capabilities

61

62

### Parsing Functions

63

64

Load and parse JSON5 documents into Python objects, supporting file objects and strings with extensive customization options.

65

66

```python { .api }

67

def load(

68

fp,

69

*,

70

encoding=None,

71

cls=None,

72

object_hook=None,

73

parse_float=None,

74

parse_int=None,

75

parse_constant=None,

76

strict=True,

77

object_pairs_hook=None,

78

allow_duplicate_keys=True,

79

consume_trailing=True,

80

start=None

81

):

82

"""

83

Deserialize fp (a .read()-supporting file-like object containing a JSON5 document) to a Python object.

84

85

Parameters:

86

- fp: file-like object with .read() method

87

- encoding: character encoding (default: UTF-8)

88

- cls: ignored (for json compatibility)

89

- object_hook: optional function to transform decoded objects

90

- parse_float: optional function to parse float values

91

- parse_int: optional function to parse integer values

92

- parse_constant: optional function to parse constants (Infinity, NaN)

93

- strict: if True, control characters (\\x00-\\x1f) in strings raise ValueError

94

- object_pairs_hook: optional function called with ordered list of key-value pairs

95

- allow_duplicate_keys: if False, duplicate keys raise ValueError

96

- consume_trailing: if True, trailing non-whitespace raises ValueError

97

- start: offset position to start parsing from in file

98

99

Returns:

100

Parsed Python object

101

102

Raises:

103

- ValueError: invalid JSON5 document

104

- UnicodeDecodeError: invalid UTF-8 encoding

105

"""

106

107

def loads(

108

s,

109

*,

110

encoding=None,

111

cls=None,

112

object_hook=None,

113

parse_float=None,

114

parse_int=None,

115

parse_constant=None,

116

strict=True,

117

object_pairs_hook=None,

118

allow_duplicate_keys=True,

119

consume_trailing=True,

120

start=None

121

):

122

"""

123

Deserialize s (a string containing a JSON5 document) to a Python object.

124

125

Parameters:

126

- s: JSON5 string to parse

127

- encoding: character encoding (default: UTF-8)

128

- cls: ignored (for json compatibility)

129

- object_hook: optional function to transform decoded objects

130

- parse_float: optional function to parse float values

131

- parse_int: optional function to parse integer values

132

- parse_constant: optional function to parse constants (Infinity, NaN)

133

- strict: if True, control characters (\\x00-\\x1f) in strings raise ValueError

134

- object_pairs_hook: optional function called with ordered list of key-value pairs

135

- allow_duplicate_keys: if False, duplicate keys raise ValueError

136

- consume_trailing: if True, trailing non-whitespace raises ValueError

137

- start: offset position to start parsing from in string

138

139

Returns:

140

Parsed Python object

141

142

Raises:

143

- ValueError: invalid JSON5 document

144

- UnicodeDecodeError: invalid UTF-8 encoding

145

"""

146

147

def parse(

148

s,

149

*,

150

encoding=None,

151

cls=None,

152

object_hook=None,

153

parse_float=None,

154

parse_int=None,

155

parse_constant=None,

156

strict=True,

157

object_pairs_hook=None,

158

allow_duplicate_keys=True,

159

consume_trailing=True,

160

start=None

161

):

162

"""

163

Parse s, returning positional information along with a value.

164

165

Useful for parsing multiple values from a single string by repeatedly calling

166

with start parameter set to the position returned from previous call.

167

168

Parameters:

169

- s: JSON5 string to parse

170

- encoding: character encoding (default: UTF-8)

171

- cls: ignored (for json compatibility)

172

- object_hook: optional function to transform decoded objects

173

- parse_float: optional function to parse float values

174

- parse_int: optional function to parse integer values

175

- parse_constant: optional function to parse constants (Infinity, NaN)

176

- strict: if True, control characters (\\x00-\\x1f) in strings raise ValueError

177

- object_pairs_hook: optional function called with ordered list of key-value pairs

178

- allow_duplicate_keys: if False, duplicate keys raise ValueError

179

- consume_trailing: if True, trailing non-whitespace raises ValueError

180

- start: offset position to start parsing from in string

181

182

Returns:

183

Tuple of (value, error_string, position):

184

- value: parsed Python object or None if error

185

- error_string: None if successful, error message if failed

186

- position: zero-based offset where parsing stopped

187

188

Raises:

189

- UnicodeDecodeError: invalid UTF-8 encoding

190

"""

191

```

192

193

#### Usage Examples

194

195

```python

196

import json5

197

198

# Basic parsing

199

data = json5.loads('{"name": "example"}')

200

201

# Parse with custom hooks

202

def custom_object_hook(obj):

203

return {k.upper(): v for k, v in obj.items()}

204

205

data = json5.loads('{"name": "example"}', object_hook=custom_object_hook)

206

# Result: {"NAME": "example"}

207

208

# Parse multiple values from string

209

s = '{"a": 1} {"b": 2} {"c": 3}'

210

values = []

211

start = 0

212

while start < len(s):

213

value, error, pos = json5.parse(s, start=start, consume_trailing=False)

214

if error:

215

break

216

values.append(value)

217

start = pos

218

# Skip whitespace

219

while start < len(s) and s[start].isspace():

220

start += 1

221

222

# Reject duplicate keys

223

try:

224

json5.loads('{"key": 1, "key": 2}', allow_duplicate_keys=False)

225

except ValueError as e:

226

print(f"Duplicate key error: {e}")

227

```

228

229

### Serialization Functions

230

231

Serialize Python objects to JSON5 format with extensive formatting and style options.

232

233

```python { .api }

234

def dump(

235

obj,

236

fp,

237

*,

238

skipkeys=False,

239

ensure_ascii=True,

240

check_circular=True,

241

allow_nan=True,

242

cls=None,

243

indent=None,

244

separators=None,

245

default=None,

246

sort_keys=False,

247

quote_keys=False,

248

trailing_commas=True,

249

allow_duplicate_keys=True,

250

quote_style=QuoteStyle.ALWAYS_DOUBLE,

251

**kwargs

252

):

253

"""

254

Serialize obj to a JSON5-formatted stream to fp (a .write()-supporting file-like object).

255

256

Parameters:

257

- obj: Python object to serialize

258

- fp: file-like object with .write() method

259

- skipkeys: if True, skip keys that are not basic types

260

- ensure_ascii: if True, escape non-ASCII characters

261

- check_circular: if True, check for circular references

262

- allow_nan: if True, allow NaN, Infinity, -Infinity

263

- cls: custom JSON5Encoder class

264

- indent: indentation (int for spaces, str for custom, None for compact)

265

- separators: (item_separator, key_separator) tuple

266

- default: function to handle non-serializable objects

267

- sort_keys: if True, sort object keys

268

- quote_keys: if True, always quote object keys

269

- trailing_commas: if True, add trailing commas in multiline output

270

- allow_duplicate_keys: if True, allow duplicate keys in output

271

- quote_style: QuoteStyle enum value controlling string quoting

272

273

Raises:

274

- TypeError: non-serializable object

275

- ValueError: circular reference or invalid value

276

"""

277

278

def dumps(

279

obj,

280

*,

281

skipkeys=False,

282

ensure_ascii=True,

283

check_circular=True,

284

allow_nan=True,

285

cls=None,

286

indent=None,

287

separators=None,

288

default=None,

289

sort_keys=False,

290

quote_keys=False,

291

trailing_commas=True,

292

allow_duplicate_keys=True,

293

quote_style=QuoteStyle.ALWAYS_DOUBLE,

294

**kwargs

295

):

296

"""

297

Serialize obj to a JSON5-formatted string.

298

299

Parameters:

300

- obj: Python object to serialize

301

- skipkeys: if True, skip keys that are not basic types

302

- ensure_ascii: if True, escape non-ASCII characters

303

- check_circular: if True, check for circular references

304

- allow_nan: if True, allow NaN, Infinity, -Infinity

305

- cls: custom JSON5Encoder class

306

- indent: indentation (int for spaces, str for custom, None for compact)

307

- separators: (item_separator, key_separator) tuple

308

- default: function to handle non-serializable objects

309

- sort_keys: if True, sort object keys

310

- quote_keys: if True, always quote object keys

311

- trailing_commas: if True, add trailing commas in multiline output

312

- allow_duplicate_keys: if True, allow duplicate keys in output

313

- quote_style: QuoteStyle enum value controlling string quoting

314

315

Returns:

316

JSON5-formatted string

317

318

Raises:

319

- TypeError: non-serializable object

320

- ValueError: circular reference or invalid value

321

"""

322

```

323

324

#### Usage Examples

325

326

```python

327

import json5

328

from json5 import QuoteStyle

329

330

# Basic serialization

331

data = {"name": "example", "values": [1, 2, 3]}

332

json5_str = json5.dumps(data)

333

334

# Pretty-printed with unquoted keys and trailing commas

335

json5_str = json5.dumps(data, indent=2, quote_keys=False, trailing_commas=True)

336

337

# Use single quotes for strings

338

json5_str = json5.dumps(data, quote_style=QuoteStyle.ALWAYS_SINGLE)

339

340

# JSON compatibility mode

341

json_str = json5.dumps(data, quote_keys=True, trailing_commas=False)

342

343

# Custom serialization

344

def custom_serializer(obj):

345

if hasattr(obj, '__dict__'):

346

return obj.__dict__

347

raise TypeError(f"Object of type {type(obj)} is not JSON5 serializable")

348

349

class Person:

350

def __init__(self, name, age):

351

self.name = name

352

self.age = age

353

354

person = Person("Alice", 30)

355

json5_str = json5.dumps(person, default=custom_serializer, indent=2)

356

```

357

358

### Encoder Classes

359

360

Customizable JSON5 encoder for advanced serialization control and extensibility.

361

362

```python { .api }

363

class JSON5Encoder:

364

"""

365

Customizable JSON5 encoder class.

366

"""

367

368

def __init__(

369

self,

370

*,

371

skipkeys=False,

372

ensure_ascii=True,

373

check_circular=True,

374

allow_nan=True,

375

indent=None,

376

separators=None,

377

default=None,

378

sort_keys=False,

379

quote_keys=False,

380

trailing_commas=True,

381

allow_duplicate_keys=True,

382

quote_style=QuoteStyle.ALWAYS_DOUBLE,

383

**kwargs

384

):

385

"""

386

Initialize JSON5 encoder with formatting options.

387

388

Parameters match those of dumps() function.

389

"""

390

391

def default(self, obj):

392

"""

393

Override to provide custom serialization for objects that are not

394

natively JSON5 serializable.

395

396

Parameters:

397

- obj: object to serialize

398

399

Returns:

400

JSON5-serializable representation of obj

401

402

Raises:

403

- TypeError: if obj cannot be serialized

404

"""

405

406

def encode(self, obj, seen, level, *, as_key=False):

407

"""

408

Return JSON5-encoded version of obj.

409

410

Parameters:

411

- obj: object to encode

412

- seen: set of object ids for circular reference detection

413

- level: current nesting level

414

- as_key: if True, encode as object key

415

416

Returns:

417

JSON5-encoded string

418

419

Raises:

420

- TypeError: unsupported object type

421

- ValueError: circular reference or invalid value

422

"""

423

424

def is_identifier(self, key):

425

"""

426

Check if key can be used as unquoted object key.

427

428

Parameters:

429

- key: string to check

430

431

Returns:

432

True if key is valid ECMAScript identifier

433

"""

434

435

def is_reserved_word(self, key):

436

"""

437

Check if key is ECMAScript reserved word.

438

439

Parameters:

440

- key: string to check

441

442

Returns:

443

True if key is reserved word

444

"""

445

```

446

447

#### Usage Examples

448

449

```python

450

import json5

451

from json5 import JSON5Encoder, QuoteStyle

452

453

# Custom encoder for special objects

454

class CustomEncoder(JSON5Encoder):

455

def default(self, obj):

456

if isinstance(obj, set):

457

return list(obj)

458

if hasattr(obj, 'isoformat'): # datetime objects

459

return obj.isoformat()

460

return super().default(obj)

461

462

# Use custom encoder

463

from datetime import datetime

464

data = {

465

"timestamp": datetime.now(),

466

"tags": {"python", "json5", "serialization"}

467

}

468

json5_str = json5.dumps(data, cls=CustomEncoder, indent=2)

469

470

# Encoder with custom quote style

471

encoder = JSON5Encoder(

472

quote_style=QuoteStyle.PREFER_SINGLE,

473

indent=2,

474

trailing_commas=True

475

)

476

json5_str = encoder.encode(data, set(), 0, as_key=False)

477

```

478

479

### String Quoting Styles

480

481

Control how strings are quoted during JSON5 serialization.

482

483

```python { .api }

484

class QuoteStyle(enum.Enum):

485

"""

486

Enum controlling how strings are quoted during encoding.

487

"""

488

489

ALWAYS_DOUBLE = 'always_double' # Always use double quotes

490

ALWAYS_SINGLE = 'always_single' # Always use single quotes

491

PREFER_DOUBLE = 'prefer_double' # Prefer double, use single if fewer escapes

492

PREFER_SINGLE = 'prefer_single' # Prefer single, use double if fewer escapes

493

```

494

495

#### Usage Examples

496

497

```python

498

import json5

499

from json5 import QuoteStyle

500

501

text = "It's a \"wonderful\" day"

502

503

# Different quote styles

504

double_quoted = json5.dumps(text, quote_style=QuoteStyle.ALWAYS_DOUBLE)

505

# Result: "\"It's a \\\"wonderful\\\" day\""

506

507

single_quoted = json5.dumps(text, quote_style=QuoteStyle.ALWAYS_SINGLE)

508

# Result: "'It\\'s a \"wonderful\" day'"

509

510

prefer_double = json5.dumps(text, quote_style=QuoteStyle.PREFER_DOUBLE)

511

# Result: "'It\\'s a \"wonderful\" day'" (fewer escapes with single quotes)

512

513

prefer_single = json5.dumps(text, quote_style=QuoteStyle.PREFER_SINGLE)

514

# Result: "'It\\'s a \"wonderful\" day'" (preferred single quotes)

515

```

516

517

### Version Information

518

519

Access package version information for compatibility and debugging.

520

521

```python { .api }

522

__version__: str # Package version string (e.g., "0.12.1")

523

VERSION: str # Backward compatibility alias for __version__

524

```

525

526

#### Usage Examples

527

528

```python

529

import json5

530

531

print(f"Using json5 version: {json5.__version__}")

532

print(f"Version (legacy): {json5.VERSION}")

533

534

# Version checking

535

from packaging import version

536

if version.parse(json5.__version__) >= version.parse("0.12.0"):

537

print("QuoteStyle enum is available")

538

```

539

540

## JSON5 Features Supported

541

542

This implementation supports all JSON5 language features:

543

544

- **Comments**: Single-line `//` and multi-line `/* */` comments

545

- **Unquoted Keys**: Object keys that are valid ECMAScript identifiers don't need quotes

546

- **Trailing Commas**: Objects and arrays can have trailing commas

547

- **Single Quotes**: Strings can be single-quoted

548

- **Multi-line Strings**: String literals can span multiple lines

549

- **Additional Number Formats**: Hexadecimal numbers (0xFF), positive/negative infinity, NaN

550

- **Escape Sequences**: All JSON escape sequences plus single quote and vertical tab

551

552

## Error Handling

553

554

The library raises standard Python exceptions:

555

556

- **ValueError**: Invalid JSON5 syntax, duplicate keys (when disabled), circular references

557

- **TypeError**: Non-serializable objects during encoding

558

- **UnicodeDecodeError**: Invalid UTF-8 byte sequences

559

560

```python

561

import json5

562

563

# Handle parsing errors

564

try:

565

data = json5.loads('{"invalid": syntax}')

566

except ValueError as e:

567

print(f"Parse error: {e}")

568

569

# Handle encoding errors

570

try:

571

json5.dumps(object()) # object() is not serializable

572

except TypeError as e:

573

print(f"Encoding error: {e}")

574

```