From 8d33364bf5d2fef5bdc3c869548b38fd19af26cb Mon Sep 17 00:00:00 2001 From: Benoit Louy Date: Mon, 12 Aug 2024 11:30:09 -0400 Subject: [PATCH] use Document.Decoder to convert the unknown values to the expected type --- .../json/internals/SchemaVisitorJCodec.scala | 59 +++++++++++-------- 1 file changed, 34 insertions(+), 25 deletions(-) diff --git a/modules/json/src/smithy4s/json/internals/SchemaVisitorJCodec.scala b/modules/json/src/smithy4s/json/internals/SchemaVisitorJCodec.scala index 16567fbe2..1f384c1ee 100644 --- a/modules/json/src/smithy4s/json/internals/SchemaVisitorJCodec.scala +++ b/modules/json/src/smithy4s/json/internals/SchemaVisitorJCodec.scala @@ -1447,10 +1447,10 @@ private[smithy4s] class SchemaVisitorJCodec( ): JCodec[Z] = new JCodec[Z] { - private[this] val isLabelForUnknownFields = - fieldsForUnknown.map { case (_, label, _) => - label - }.toSet + private val fieldForUnknownDocumentDecoders = fieldsForUnknown.map { + case (field, label, _) => + label -> Document.Decoder.fromSchema(field.schema) + }.toMap private[this] val handlers = new util.HashMap[String, Handler](knownFields.length << 1, 0.5f) { @@ -1501,30 +1501,39 @@ private[smithy4s] class SchemaVisitorJCodec( meta.foreach(kv => buffer.put(kv._1, kv._2)) val stage2 = new VectorBuilder[Any] val unknownValue = - if (unknownValues.nonEmpty) { - val builder = Map.newBuilder[String, Document] - builder ++= unknownValues - builder.result() - } else null + if (unknownValues.nonEmpty) Document.obj(unknownValues) else null allFields.foreach { case (f, jsonLabel, default) => stage2 += { - if (isLabelForUnknownFields(jsonLabel)) { - if (unknownValue == null) { - if (default == null) { - if (f.isRequired) Map.empty - else None - } else default - } else { - if (f.isRequired) unknownValue else Some(unknownValue) - } - } else { - val value = buffer.get(f.label) - if (value == null) { - if (default == null) - cursor.requiredFieldError(jsonLabel, jsonLabel) - else default - } else value + fieldForUnknownDocumentDecoders.get(jsonLabel) match { + case None => + val value = buffer.get(f.label) + if (value == null) { + if (default == null) + cursor.requiredFieldError(jsonLabel, jsonLabel) + else default + } else value + + case Some(docDecoder) => + if (unknownValue == null) { + if (default == null) { + docDecoder + .decode(Document.obj()) + .getOrElse( + throw new RuntimeException( + s"${cursor.getPath(Nil)} Failed translating a Document.DObject to the type targeted by ${f.label}." + ) + ) + } else default + } else { + docDecoder + .decode(unknownValue) + .getOrElse( + throw new RuntimeException( + s"${cursor.getPath(Nil)} Failed translating a Document.DObject to the type targeted by ${f.label}." + ) + ) + } } } }