or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cursor-navigation.mderror-handling.mdindex.mdjson-data-types.mdjson-printing.mdkey-encoding-decoding.mdtype-classes.md

json-printing.mddocs/

0

# JSON Printing

1

2

Circe provides flexible and configurable JSON printing through the Printer class. It offers various formatting options, performance optimizations, and output formats.

3

4

## Printer

5

6

Configurable JSON pretty-printer for formatting JSON output.

7

8

```scala { .api }

9

final case class Printer(

10

dropNullValues: Boolean,

11

indent: String,

12

lbraceLeft: String = "",

13

lbraceRight: String = "",

14

rbraceLeft: String = "",

15

rbraceRight: String = "",

16

lbracketLeft: String = "",

17

lbracketRight: String = "",

18

rbracketLeft: String = "",

19

rbracketRight: String = "",

20

lrbracketsEmpty: String = "",

21

arrayCommaLeft: String = "",

22

arrayCommaRight: String = "",

23

objectCommaLeft: String = "",

24

objectCommaRight: String = "",

25

colonLeft: String = "",

26

colonRight: String = "",

27

reuseWriters: Boolean = false,

28

predictSize: Boolean = false,

29

escapeNonAscii: Boolean = false,

30

sortKeys: Boolean = false

31

) {

32

// Core printing methods

33

def print(json: Json): String

34

def printToByteBuffer(json: Json, cs: Charset): ByteBuffer

35

def printToByteBuffer(json: Json): ByteBuffer

36

def unsafePrintToAppendable(json: Json, out: Appendable): Unit

37

38

// Configuration

39

def withSortedKeys: Printer

40

}

41

```

42

43

### Printer Companion Object

44

45

```scala { .api }

46

object Printer {

47

// Predefined configurations

48

val noSpaces: Printer

49

val noSpacesSortKeys: Printer

50

val spaces2: Printer

51

val spaces2SortKeys: Printer

52

val spaces4: Printer

53

val spaces4SortKeys: Printer

54

55

// Custom indentation

56

def indented(indent: String, sortKeys: Boolean = false): Printer

57

}

58

```

59

60

## Usage Examples

61

62

### Basic Printing

63

64

```scala

65

import io.circe._

66

import io.circe.syntax._

67

68

val json = Json.obj(

69

"name" -> Json.fromString("John"),

70

"age" -> Json.fromInt(30),

71

"active" -> Json.fromBoolean(true),

72

"scores" -> Json.arr(Json.fromInt(85), Json.fromInt(92), Json.fromInt(78))

73

)

74

75

// Compact printing (no spaces)

76

val compact = json.noSpaces

77

// Result: {"name":"John","age":30,"active":true,"scores":[85,92,78]}

78

79

// Pretty printing with 2 spaces

80

val pretty2 = json.spaces2

81

// Result:

82

// {

83

// "name" : "John",

84

// "age" : 30,

85

// "active" : true,

86

// "scores" : [

87

// 85,

88

// 92,

89

// 78

90

// ]

91

// }

92

93

// Pretty printing with 4 spaces

94

val pretty4 = json.spaces4

95

// Result:

96

// {

97

// "name" : "John",

98

// "age" : 30,

99

// "active" : true,

100

// "scores" : [

101

// 85,

102

// 92,

103

// 78

104

// ]

105

// }

106

```

107

108

### Custom Printer Configuration

109

110

```scala

111

import io.circe._

112

113

val json = Json.obj(

114

"name" -> Json.fromString("John"),

115

"email" -> Json.Null,

116

"age" -> Json.fromInt(30)

117

)

118

119

// Custom printer that drops null values

120

val customPrinter = Printer(

121

dropNullValues = true,

122

indent = " ",

123

lbraceRight = "\n",

124

rbraceLeft = "\n",

125

arrayCommaRight = "\n",

126

objectCommaRight = "\n",

127

colonLeft = " ",

128

colonRight = " "

129

)

130

131

val result = customPrinter.print(json)

132

// Result:

133

// {

134

// "name" : "John",

135

// "age" : 30

136

// }

137

// Note: "email": null is omitted

138

```

139

140

### Sorted Keys

141

142

```scala

143

import io.circe._

144

145

val json = Json.obj(

146

"zebra" -> Json.fromString("animal"),

147

"apple" -> Json.fromString("fruit"),

148

"banana" -> Json.fromString("fruit"),

149

"ant" -> Json.fromString("insect")

150

)

151

152

// Default order (insertion order)

153

val unsorted = json.spaces2

154

// Result:

155

// {

156

// "zebra" : "animal",

157

// "apple" : "fruit",

158

// "banana" : "fruit",

159

// "ant" : "insect"

160

// }

161

162

// Sorted keys

163

val sorted = json.printWith(Printer.spaces2SortKeys)

164

// Result:

165

// {

166

// "ant" : "insect",

167

// "apple" : "fruit",

168

// "banana" : "fruit",

169

// "zebra" : "animal"

170

// }

171

172

// Or using withSortedKeys

173

val sortedCustom = Printer.spaces4.withSortedKeys.print(json)

174

```

175

176

### Performance Optimizations

177

178

```scala

179

import io.circe._

180

import java.nio.charset.StandardCharsets

181

182

val largeJson = Json.obj(

183

"data" -> Json.arr((1 to 1000).map(i => Json.obj(

184

"id" -> Json.fromInt(i),

185

"value" -> Json.fromString(s"item-$i")

186

)): _*)

187

)

188

189

// Reuse writers for better performance in multi-threaded scenarios

190

val optimizedPrinter = Printer(

191

dropNullValues = false,

192

indent = "",

193

reuseWriters = true,

194

predictSize = true

195

)

196

197

// String output

198

val jsonString = optimizedPrinter.print(largeJson)

199

200

// Binary output for network transmission

201

val byteBuffer = optimizedPrinter.printToByteBuffer(largeJson, StandardCharsets.UTF_8)

202

val bytes = new Array[Byte](byteBuffer.remaining())

203

byteBuffer.get(bytes)

204

```

205

206

### Unicode Handling

207

208

```scala

209

import io.circe._

210

211

val json = Json.obj(

212

"message" -> Json.fromString("Hello δΈ–η•Œ! 🌍"),

213

"emoji" -> Json.fromString("πŸ˜€ πŸ˜ƒ πŸ˜„ 😁")

214

)

215

216

// Default: preserves Unicode characters

217

val withUnicode = json.noSpaces

218

// Result: {"message":"Hello δΈ–η•Œ! 🌍","emoji":"πŸ˜€ πŸ˜ƒ πŸ˜„ 😁"}

219

220

// Escape non-ASCII characters

221

val unicodeEscaped = Printer(

222

dropNullValues = false,

223

indent = "",

224

escapeNonAscii = true

225

).print(json)

226

// Result: {"message":"Hello \\u4e16\\u754c! \\ud83c\\udf0d","emoji":"\\ud83d\\ude00 \\ud83d\\ude03 \\ud83d\\ude04 \\ud83d\\ude01"}

227

```

228

229

### Custom Formatting

230

231

```scala

232

import io.circe._

233

234

val json = Json.obj(

235

"users" -> Json.arr(

236

Json.obj("name" -> Json.fromString("Alice")),

237

Json.obj("name" -> Json.fromString("Bob"))

238

)

239

)

240

241

// Minimal spacing

242

val minimal = Printer(

243

dropNullValues = false,

244

indent = "",

245

colonRight = " ",

246

arrayCommaRight = " ",

247

objectCommaRight = " "

248

).print(json)

249

// Result: {"users": [{"name": "Alice"}, {"name": "Bob"}]}

250

251

// Custom indentation with tabs

252

val tabIndented = Printer(

253

dropNullValues = false,

254

indent = "\t",

255

lbraceRight = "\n",

256

rbraceLeft = "\n",

257

lbracketRight = "\n",

258

rbracketLeft = "\n",

259

arrayCommaRight = "\n",

260

objectCommaRight = "\n",

261

colonLeft = " ",

262

colonRight = " "

263

).print(json)

264

// Uses tabs for indentation

265

266

// No spacing around arrays

267

val compactArrays = Printer(

268

dropNullValues = false,

269

indent = " ",

270

lbraceRight = "\n",

271

rbraceLeft = "\n",

272

objectCommaRight = "\n",

273

colonLeft = " ",

274

colonRight = " "

275

// Arrays remain compact: no lbracketRight/rbracketLeft

276

).print(json)

277

```

278

279

### Working with Appendable

280

281

```scala

282

import io.circe._

283

import java.io.StringWriter

284

285

val json = Json.obj("message" -> Json.fromString("Hello World"))

286

287

// Write to StringBuilder

288

val builder = new StringBuilder()

289

Printer.noSpaces.unsafePrintToAppendable(json, builder)

290

val result1 = builder.toString

291

292

// Write to StringWriter

293

val writer = new StringWriter()

294

Printer.spaces2.unsafePrintToAppendable(json, writer)

295

val result2 = writer.toString

296

297

// Write to any Appendable

298

class CustomAppendable extends Appendable {

299

private val buffer = new StringBuilder()

300

301

def append(csq: CharSequence): Appendable = {

302

buffer.append(csq)

303

this

304

}

305

306

def append(csq: CharSequence, start: Int, end: Int): Appendable = {

307

buffer.append(csq, start, end)

308

this

309

}

310

311

def append(c: Char): Appendable = {

312

buffer.append(c)

313

this

314

}

315

316

def getResult: String = buffer.toString

317

}

318

319

val custom = new CustomAppendable()

320

Printer.noSpaces.unsafePrintToAppendable(json, custom)

321

val result3 = custom.getResult

322

```

323

324

### Binary Output

325

326

```scala

327

import io.circe._

328

import java.nio.charset.{Charset, StandardCharsets}

329

import java.nio.ByteBuffer

330

331

val json = Json.obj(

332

"text" -> Json.fromString("Hello"),

333

"number" -> Json.fromInt(42)

334

)

335

336

// UTF-8 output (default)

337

val utf8Buffer = Printer.noSpaces.printToByteBuffer(json)

338

val utf8Bytes = new Array[Byte](utf8Buffer.remaining())

339

utf8Buffer.get(utf8Bytes)

340

val utf8String = new String(utf8Bytes, StandardCharsets.UTF_8)

341

342

// UTF-16 output

343

val utf16Buffer = Printer.noSpaces.printToByteBuffer(json, StandardCharsets.UTF_16)

344

val utf16Bytes = new Array[Byte](utf16Buffer.remaining())

345

utf16Buffer.get(utf16Bytes)

346

val utf16String = new String(utf16Bytes, StandardCharsets.UTF_16)

347

348

// ASCII with escaped Unicode

349

val asciiPrinter = Printer(

350

dropNullValues = false,

351

indent = "",

352

escapeNonAscii = true

353

)

354

val asciiBuffer = asciiPrinter.printToByteBuffer(json, StandardCharsets.US_ASCII)

355

```

356

357

### Error Handling in Printing

358

359

```scala

360

import io.circe._

361

362

// Printing generally doesn't fail, but here are edge cases

363

val problematicJson = Json.fromDouble(Double.NaN)

364

365

problematicJson match {

366

case Some(json) =>

367

val printed = json.noSpaces

368

println(s"Printed: $printed")

369

case None =>

370

println("Cannot create JSON from NaN")

371

}

372

373

// Infinite values

374

val infiniteJson = Json.fromDouble(Double.PositiveInfinity)

375

infiniteJson match {

376

case Some(json) =>

377

val printed = json.noSpaces

378

println(s"Printed: $printed") // "null"

379

case None =>

380

println("Cannot create JSON from infinite value")

381

}

382

```

383

384

### Streaming and Large JSON

385

386

```scala

387

import io.circe._

388

import java.io.{FileWriter, BufferedWriter}

389

390

// For very large JSON, use unsafePrintToAppendable with a buffered writer

391

val largeJson = Json.obj(

392

"items" -> Json.arr(

393

(1 to 100000).map(i => Json.obj(

394

"id" -> Json.fromInt(i),

395

"data" -> Json.fromString(s"data-$i")

396

)): _*

397

)

398

)

399

400

// Write directly to file

401

val fileWriter = new BufferedWriter(new FileWriter("large.json"))

402

try {

403

Printer.noSpaces.unsafePrintToAppendable(largeJson, fileWriter)

404

} finally {

405

fileWriter.close()

406

}

407

408

// Or use ByteBuffer for binary output

409

val buffer = Printer.noSpaces.printToByteBuffer(largeJson)

410

// Can write buffer to FileChannel, SocketChannel, etc.

411

```

412

413

### Printer Performance Comparison

414

415

```scala

416

import io.circe._

417

418

val testJson = Json.obj(

419

"data" -> Json.arr((1 to 1000).map(Json.fromInt): _*)

420

)

421

422

// Compact printing (fastest)

423

val compact = Printer.noSpaces

424

val compactResult = compact.print(testJson)

425

426

// Pretty printing (slower due to whitespace)

427

val pretty = Printer.spaces2

428

val prettyResult = pretty.print(testJson)

429

430

// With optimizations (fastest for repeated use)

431

val optimized = Printer(

432

dropNullValues = false,

433

indent = "",

434

reuseWriters = true,

435

predictSize = true

436

)

437

val optimizedResult = optimized.print(testJson)

438

439

// With sorted keys (slowest due to sorting)

440

val sorted = Printer.noSpacesSortKeys

441

val sortedResult = sorted.print(testJson)

442

```