Empty default handling
Inference of defaults on members with null @default
In #782, we added this semantic: adding an empty @default trait to a shape makes that shape's default the "empty" value of the target type.
For example:
//> using scala "2.13.10"
//> using option "-feature"
//> using lib "software.amazon.smithy:smithy-model:1.28.1"
//> using lib "com.disneystreaming.smithy4s::smithy4s-dynamic:0.17.5"
import software.amazon.smithy.model.Model
import software.amazon.smithy.model.shapes.ShapeId
import software.amazon.smithy.model.traits.DefaultTrait
import smithy4s.dynamic.DynamicSchemaIndex
import smithy4s.schema.Schema
import scala.language.existentials
val s =
"""$version: "2"
|namespace test
|
|structure Hello {
| @default s: String
|}
|""".stripMargin
val m = Model.assembler().addUnparsedModel("test.smithy", s).assemble().unwrap()
DynamicSchemaIndex
.loadModel(m)
.toTry
.get
.getSchema(smithy4s.ShapeId("test", "Hello"))
.get
.asInstanceOf[Schema.StructSchema[_]]
.fields
.head
.instance
.getDefaultValue
// res0: Option[_1.T] = Some(value = "")
Quoting Michael's comment here:
Setting a member to have a default value of null is only useful if the shape targeted by the member defines a default value. It's only meaning is that it cancels out the default value of the target shape.
With that in mind, I believe this part is wrong:
// res0: Option[_1.T] = Some(value = "")
I believe it should be None instead.
Defaults on document shapes
However! I think the behavior is correct for documents:
Setting a document type null is also meaningless and there's no way to set a document type to have a default value of null since that's already the assumed value if it isn't specified
so if the schema in question was @default s: Document, that field's default should be Some(Document.DNull).
Related: https://github.com/disneystreaming/smithy4s/pull/823 introduced defaults for the schema of the Dynamic model, which I believe won't work if we update the semantics for non-documents (@default will be different from @default([])).
sigh I'm really not liking the distinction between :
@default s: Document<=>s: Option[Document] = Some(Document.DNull)@default s: Integer<=>s: Option[Int] = None
I'm gonna have to digest this further (it's not because AWS says something that it's the right thing to do)
if you ask me, @default s: Document may as well decode to None. I'm just not a fan of the current semantics
I'm just not a fan of the current semantics
Agreed