Skip to content

Commit 933b790

Browse files
committed
More efficient parsing of case classes with 1 to 22 fields
1 parent 38ad7c5 commit 933b790

File tree

1 file changed

+28
-27
lines changed

1 file changed

+28
-27
lines changed

zio-schema-json/shared/src/main/scala/zio/schema/codec/JsonCodec.scala

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1540,7 +1540,7 @@ object JsonCodec {
15401540
//scalafmt: { maxColumn = 120, optIn.configStyleArguments = true }
15411541

15421542
private class CaseClassJsonDecoder[Z](
1543-
fields: Array[Schema.Field[Z, _]],
1543+
defaults: Array[Any],
15441544
fieldDecoders: Array[ZJsonDecoder[_]],
15451545
spans: Array[JsonError.ObjectAccess],
15461546
stringMatrix: StringMatrix,
@@ -1549,7 +1549,7 @@ object JsonCodec {
15491549
) {
15501550

15511551
def unsafeDecodeFields(trace: List[JsonError], in: RetractReader): Array[Any] = {
1552-
val len = fields.length
1552+
val len = defaults.length
15531553
val buffer = new Array[Any](len)
15541554
var reader = in
15551555
var continue =
@@ -1566,28 +1566,17 @@ object JsonCodec {
15661566
else if (idx >= 0) {
15671567
if (buffer(idx) != null) error(trace, "duplicate")
15681568
else buffer(idx) = fieldDecoders(idx).unsafeDecode(spans(idx) :: trace, reader)
1569-
} else if (!rejectExtraFields) Lexer.skipValue(trace, reader)
1570-
else error(trace, "extra field")
1569+
} else if (rejectExtraFields) error(trace, "extra field")
1570+
else Lexer.skipValue(trace, reader)
15711571
continue = Lexer.nextField(trace, reader)
15721572
pos += 1
15731573
}
15741574
var idx = 0
15751575
while (idx < len) {
15761576
if (buffer(idx) == null) {
1577-
val field = fields(idx)
1578-
if ((field.optional || field.transient) && field.defaultValue.isDefined) {
1579-
buffer(idx) = field.defaultValue.get
1580-
} else {
1581-
val schema = field.schema match {
1582-
case l @ Schema.Lazy(_) => l.schema
1583-
case s => s
1584-
}
1585-
buffer(idx) = schema match {
1586-
case _: Schema.Optional[_] => None
1587-
case collection: Schema.Collection[_, _] => collection.empty
1588-
case _ => error(spans(idx) :: trace, "missing")
1589-
}
1590-
}
1577+
val default = defaults(idx)
1578+
if (default == null) error(spans(idx) :: trace, "missing")
1579+
buffer(idx) = default
15911580
}
15921581
idx += 1
15931582
}
@@ -1602,26 +1591,38 @@ object JsonCodec {
16021591

16031592
def apply[Z](schema: Schema.Record[Z], discriminator: Int): CaseClassJsonDecoder[Z] = {
16041593
val len = schema.fields.length
1605-
val fields = new Array[Schema.Field[Z, _]](len)
1594+
val defaults = new Array[Any](len)
16061595
val decoders = new Array[ZJsonDecoder[_]](len)
16071596
val spans = new Array[JsonError.ObjectAccess](len)
16081597
val names = new Array[String](len)
16091598
val aliases = Array.newBuilder[(String, Int)]
1610-
var i = 0
1599+
var idx = 0
16111600
schema.fields.foreach { field =>
16121601
val name = field.name.asInstanceOf[String]
1613-
fields(i) = field
1614-
names(i) = name
1615-
spans(i) = JsonError.ObjectAccess(name)
1616-
decoders(i) = schemaDecoder(field.schema)
1602+
names(idx) = name
1603+
spans(idx) = JsonError.ObjectAccess(name)
1604+
decoders(idx) = schemaDecoder(field.schema)
16171605
field.annotations.foreach {
1618-
case annotation: fieldNameAliases => annotation.aliases.foreach(a => aliases += ((a, i)))
1606+
case annotation: fieldNameAliases => annotation.aliases.foreach(a => aliases += ((a, idx)))
16191607
case _ =>
16201608
}
1621-
i += 1
1609+
defaults(idx) =
1610+
if ((field.optional || field.transient) && field.defaultValue.isDefined) field.defaultValue.get
1611+
else {
1612+
val schema = field.schema match {
1613+
case l @ Schema.Lazy(_) => l.schema
1614+
case s => s
1615+
}
1616+
schema match {
1617+
case _: Schema.Optional[_] => None
1618+
case collection: Schema.Collection[_, _] => collection.empty
1619+
case _ => null
1620+
}
1621+
}
1622+
idx += 1
16221623
}
16231624
new CaseClassJsonDecoder(
1624-
fields,
1625+
defaults,
16251626
decoders,
16261627
spans,
16271628
new StringMatrix(names, aliases.result()),

0 commit comments

Comments
 (0)