or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

builtin-types.mdcore-serialization.mdindex.mdjson-integration.mdmessagepack-integration.mdsealed-traits.mdstreaming.mdtype-classes.md

type-classes.mddocs/

0

# Type Classes

1

2

Reader, Writer, and ReadWriter type classes define serialization behavior for types in uPickle. These are the core abstractions that enable automatic and custom serialization.

3

4

## Capabilities

5

6

### Reader Type Class

7

8

Represents the ability to read (deserialize) a value of type T from structured data.

9

10

```scala { .api }

11

/**

12

* Represents the ability to read a value of type T

13

* Extends Visitor for processing structured data traversal

14

*/

15

trait Reader[T] extends upickle.core.Visitor[Any, T] {

16

def map[Z](f: T => Z): Reader[Z]

17

def mapNulls[Z](f: T => Z): Reader[Z]

18

def narrow[K <: T]: Reader[K]

19

}

20

```

21

22

**Usage Examples:**

23

24

```scala

25

import upickle.default._

26

import upickle.core._

27

28

// Custom reader for a simple case

29

implicit val customIntReader: Reader[Int] = new SimpleReader[Int] {

30

override def expectedMsg = "expected integer"

31

override def visitInt32(d: Int, index: Int) = d

32

override def visitString(s: CharSequence, index: Int) = s.toString.toInt

33

}

34

35

// Transform existing reader

36

val positiveIntReader = IntReader.map(math.abs)

37

38

// Use reader directly

39

val result = customIntReader.transform(ujson.parse("42"))

40

```

41

42

### Writer Type Class

43

44

Represents the ability to write (serialize) a value of type T to structured data.

45

46

```scala { .api }

47

/**

48

* Represents the ability to write a value of type T

49

* Extends Transformer for converting values to structured data

50

*/

51

trait Writer[T] extends Transformer[T] {

52

def isJsonDictKey: Boolean

53

def narrow[K]: Writer[K]

54

def write0[V](out: Visitor[_, V], v: T): V

55

def write[V](out: Visitor[_, V], v: T): V

56

def comap[U](f: U => T): Writer[U]

57

def comapNulls[U](f: U => T): Writer[U]

58

}

59

```

60

61

**Usage Examples:**

62

63

```scala

64

import upickle.default._

65

import upickle.core._

66

67

// Custom writer for a simple case

68

implicit val customIntWriter: Writer[Int] = new Writer[Int] {

69

override def isJsonDictKey = true

70

def write0[V](out: Visitor[_, V], v: Int): V = {

71

out.visitString(s"number_$v", -1)

72

}

73

}

74

75

// Transform existing writer

76

case class UserId(id: Int)

77

implicit val userIdWriter: Writer[UserId] = IntWriter.comap(_.id)

78

79

// Use writer directly

80

val json = customIntWriter.transform(42, ujson.StringRenderer()).toString

81

```

82

83

### ReadWriter Type Class

84

85

Combined Reader and Writer with additional utilities for bidirectional serialization.

86

87

```scala { .api }

88

/**

89

* A combined Reader and Writer, along with some utility methods

90

*/

91

trait ReadWriter[T] extends Reader[T] with Writer[T] {

92

override def narrow[K]: ReadWriter[K]

93

def bimap[V](f: V => T, g: T => V): ReadWriter[V]

94

}

95

```

96

97

**Usage Examples:**

98

99

```scala

100

import upickle.default._

101

102

// Custom ReadWriter

103

case class Temperature(celsius: Double)

104

105

implicit val temperatureRW: ReadWriter[Temperature] =

106

readwriter[Double].bimap(Temperature(_), _.celsius)

107

108

// Use bidirectionally

109

val temp = Temperature(25.0)

110

val json = write(temp) // Uses Writer part

111

val parsed = read[Temperature](json) // Uses Reader part

112

```

113

114

### Reader Companion Object

115

116

Utilities for creating and combining Reader instances.

117

118

```scala { .api }

119

object Reader {

120

/**

121

* Merges multiple tagged readers for sealed trait handling

122

*/

123

def merge[T](tagKey: String, readers: Reader[_ <: T]*): TaggedReader.Node[T]

124

def merge[T](readers: Reader[_ <: T]*): TaggedReader.Node[T]

125

126

/**

127

* Delegates reader functionality to another visitor

128

*/

129

class Delegate[T, V](delegatedReader: Visitor[T, V]) extends Reader[V]

130

131

/**

132

* Maps reader output through a transformation function

133

*/

134

abstract class MapReader[-T, V, Z](delegatedReader: Visitor[T, V]) extends Reader[Z]

135

}

136

```

137

138

**Usage Examples:**

139

140

```scala

141

import upickle.default._

142

import upickle.core._

143

144

// Merge readers for sealed trait

145

sealed trait Animal

146

case class Dog(name: String) extends Animal

147

case class Cat(name: String) extends Animal

148

149

val animalReader = Reader.merge[Animal](

150

reader[Dog], reader[Cat]

151

)

152

```

153

154

### Writer Companion Object

155

156

Utilities for creating and combining Writer instances.

157

158

```scala { .api }

159

object Writer {

160

/**

161

* Merges multiple tagged writers for sealed trait handling

162

*/

163

def merge[T](writers: Writer[_ <: T]*): TaggedWriter.Node[T]

164

165

/**

166

* Maps writer input through a transformation function

167

*/

168

class MapWriter[U, T](src: Writer[T], f: U => T) extends Writer[U]

169

170

/**

171

* Maps writer input with null handling

172

*/

173

class MapWriterNulls[U, T](src: Writer[T], f: U => T) extends Writer[U]

174

}

175

```

176

177

### ReadWriter Companion Object

178

179

Utilities for creating and combining ReadWriter instances.

180

181

```scala { .api }

182

object ReadWriter {

183

/**

184

* Merges multiple tagged readwriters for sealed trait handling

185

*/

186

def merge[T](tagKey: String, rws: ReadWriter[_ <: T]*): TaggedReadWriter[T]

187

def merge[T](rws: ReadWriter[_ <: T]*): TaggedReadWriter[T]

188

189

/**

190

* Joins separate Reader and Writer into ReadWriter

191

*/

192

implicit def join[T](implicit r0: Reader[T], w0: Writer[T]): ReadWriter[T]

193

194

/**

195

* Delegates readwriter functionality

196

*/

197

abstract class Delegate[T](other: Visitor[Any, T]) extends ReadWriter[T]

198

}

199

```

200

201

**Usage Examples:**

202

203

```scala

204

import upickle.default._

205

206

// Join separate instances

207

implicit val stringReader: Reader[String] = StringReader

208

implicit val stringWriter: Writer[String] = StringWriter

209

implicit val stringRW: ReadWriter[String] = ReadWriter.join[String]

210

211

// Merge for sealed traits

212

sealed trait Shape

213

case class Circle(radius: Double) extends Shape

214

case class Rectangle(width: Double, height: Double) extends Shape

215

216

implicit val shapeRW = ReadWriter.merge[Shape](

217

readwriter[Circle], readwriter[Rectangle]

218

)

219

```

220

221

### Key Utilities

222

223

Functions for marking types as suitable for JSON dictionary keys.

224

225

```scala { .api }

226

/**

227

* Mark a ReadWriter[T] as something that can be used as a key in a JSON dictionary

228

*/

229

def stringKeyRW[T](readwriter: ReadWriter[T]): ReadWriter[T]

230

231

/**

232

* Mark a Writer[T] as something that can be used as a key in a JSON dictionary

233

*/

234

def stringKeyW[T](readwriter: Writer[T]): Writer[T]

235

```

236

237

**Usage Examples:**

238

239

```scala

240

import upickle.default._

241

242

// Custom ID type that can be used as map key

243

case class ProductId(id: String)

244

245

implicit val productIdRW: ReadWriter[ProductId] =

246

stringKeyRW(readwriter[String].bimap(ProductId(_), _.id))

247

248

// Now can serialize Map[ProductId, Product]

249

val productMap: Map[ProductId, Product] = Map(

250

ProductId("abc") -> Product("Widget", 10.0)

251

)

252

253

val json = write(productMap)

254

// Result: {"abc": {"name": "Widget", "price": 10.0}}

255

```

256

257

## Types

258

259

```scala { .api }

260

trait SimpleReader[T] extends Reader[T] with upickle.core.SimpleVisitor[Any, T]

261

262

trait ObjectWriter[T] extends Writer[T] {

263

def length(v: T): Int

264

def writeToObject[R](ctx: ObjVisitor[_, R], v: T): Unit

265

}

266

267

/**

268

* Implicit to indicate that we are currently deriving an implicit T

269

* Used to avoid infinite recursion in implicit derivation

270

*/

271

class CurrentlyDeriving[T]

272

```