Skip to content

Commit

Permalink
Allow data class with one field to be considered a value type #164
Browse files Browse the repository at this point in the history
  • Loading branch information
sksamuel committed Dec 29, 2020
1 parent b19965a commit e35f909
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.sksamuel.hoplite.ConfigResult
import com.sksamuel.hoplite.DecoderContext
import com.sksamuel.hoplite.Node
import com.sksamuel.hoplite.ParameterMapper
import com.sksamuel.hoplite.PrimitiveNode
import com.sksamuel.hoplite.Undefined
import com.sksamuel.hoplite.fp.ValidatedNel
import com.sksamuel.hoplite.fp.flatMap
Expand Down Expand Up @@ -43,6 +44,15 @@ class DataClassDecoder : NullHandlingDecoder<Any> {
return ConfigFailure.DataClassWithoutConstructor(klass).invalid()
val constructor = klass.constructors.first()

// we have a special case, which is a data class with a single field with the name 'value'.
// we call this a "value type" and we can instantiate a value directly into this data class
// without needing nested config, if the node is a primitive type

// try for the value type
if (constructor.parameters.size == 1 && constructor.parameters[0].name == "value" && node is PrimitiveNode) {
return construct(type, constructor, mapOf(constructor.parameters.first() to node.value))
}

// create a map of parameter to value. in the case of defaults, we skip the parameter completely.
val args: ValidatedNel<ConfigFailure, List<Pair<KParameter, Any?>>> = constructor.parameters.mapNotNull { param ->

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.sksamuel.hoplite.yaml

import com.sksamuel.hoplite.ConfigLoader
import io.kotest.core.spec.style.StringSpec
import io.kotest.matchers.shouldBe

class ValueTypeDecoderTest : StringSpec({
"single value field as value type" {

// host.value doesn't exist in the config, but because it is a value type, the value of "host"
// will be used instead
data class Host(val value: String)
data class Server(val host: Host)
data class Config(val server: Server)

val config = ConfigLoader().loadConfigOrThrow<Config>("/value_type.yml")
config shouldBe Config(Server(Host("localhost")))
}
})
2 changes: 2 additions & 0 deletions hoplite-yaml/src/test/resources/value_type.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
server:
host: localhost

0 comments on commit e35f909

Please sign in to comment.