Skip to content

Commit

Permalink
reading from various sources.
Browse files Browse the repository at this point in the history
  • Loading branch information
khajavi committed May 22, 2024
1 parent fa13bcc commit 62116f9
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 97 deletions.
2 changes: 1 addition & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,5 +57,5 @@ libraryDependencies += "dev.zio" %% "zio-config-magnolia" % "<version>" // for d

```scala mdoc:passthrough
import utils._
printSource("examples/shared/src/main/scala/zio/config/examples/YamlConfigReaderExample.scala")
printSource("examples/shared/src/main/scala/zio/config/examples/configsources/YamlConfigReaderExample.scala")
```
186 changes: 90 additions & 96 deletions docs/read-from-various-sources.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,141 +3,134 @@ id: read-from-various-sources
title: "Read from various Sources"
---

zio-config supports various sources.
ZIO Config supports various sources for reading configurations. In this guide, we will see how to read configurations from different sources such as in-memory maps, HOCON strings, files, YAML, and XML.

```scala mdoc:silent
import zio._, Config._, ConfigProvider._
import zio.config._, magnolia._
```
## In-memory Map Source

```scala mdoc:silent
case class MyConfig(ldap: String, port: Int, dburl: String)
To load configs from an in-memory map, you can use `ConfigProvider.fromMap` method:

```scala mdoc:passthrough
import utils._
printSource("examples/shared/src/main/scala/zio/config/examples/configsources/InmemoryMapSourceExample.scala")
```

```scala mdoc:silent
val myConfig =
(string("LDAP") zip int("PORT") zip string("DB_URL")).to[MyConfig]
## Typesafe (HOCON) Config Source

// val automatedConfig = deriveConfig[MyConfig]; using zio-config-magnolia
```
To enable HOCON source, we have to add the `zio-config-typesafe` module to our dependencies in `build.sbt` file:

```scala
libraryDependencies += "dev.zio" %% "zio-config-typesafe" % "@VERSION@"
```

## HOCON String
By importing the `zio.config.typesafe._` module, we can read configs from HOCON sources.

To enable HOCON source, you have to bring in `zio-config-typesafe` module.
There are many examples in examples module in zio-config.
### HOCON String

Here is an quick example
We can use `ConfigProvider.fromHoconString` to load configs from a HOCON string:

```scala mdoc:silent
import zio.config.typesafe._
import zio.config.magnolia._
```scala mdoc:passthrough
import utils._
printSource("examples/shared/src/main/scala/zio/config/examples/configsources/TypesafeHoconStringSourceExample.scala")
```

```scala mdoc:silent
case class SimpleConfig(port: Int, url: String, region: Option[String])
### HOCON File

val automaticDescription = deriveConfig[SimpleConfig]
Similar to the above example, we can read configs from a HOCON file, using `ConfigProvider.fromHoconFile`.

val hoconSource =
ConfigProvider.fromHoconString(
"""
{
port : 123
url : bla
region: useast
}
"""
)
Assume we have a HOCON file `application.simple.conf` in the `resources` directory:

val anotherHoconSource =
ConfigProvider.fromHoconString(
"""
port=123
url=bla
region=useast
"""
)
```scala mdoc:passthrough
import utils._
printSource("examples/shared/src/main/resources/application.simple.conf")
```

hoconSource.load(deriveConfig[SimpleConfig])
We can read the configuration file as follows:

// yielding SimpleConfig(123,bla,Some(useast))
```scala mdoc:passthrough
import utils._
printSource("examples/shared/src/main/scala/zio/config/examples/configsources/TypesafeHoconFileSourceExample.scala")
```

## HOCON File
### JSON File

We can use `zio-config-typesafe` module to fetch json as well. So let's add it to our `build.sbt` file:

```scala mdoc:silent
ConfigProvider.fromHoconFile(new java.io.File("fileapth"))
```scala
libraryDependencies += "dev.zio" %% "zio-config-typesafe" % "@VERSION@"
```

## Json
Assume we have a JSON file `application.json` in the `resources` directory:

You can use `zio-config-typesafe` module to fetch json as well
```scala mdoc:passthrough
import utils._
printSource("examples/shared/src/main/resources/application.json")
```

```scala mdoc:silent
val jsonString =
"""
{
"port" : "123"
"url" : "bla"
"region": "useast"
}
"""
We can read the configuration file as follows:

ConfigProvider.fromHoconString(jsonString)
```scala mdoc:passthrough
import utils._
printSource("examples/shared/src/main/scala/zio/config/examples/configsources/TypesafeJsonFileSourceExample.scala")
```

## Yaml FIle
## YAML Source

Similar to Hocon source, we have `ConfigProvider.fromYamlString`
Let's add these four lines to our `build.sbt` file as we are using these modules in our examples:

```scala
import zio.config.yaml._
libraryDependencies += "dev.zio" %% "zio-config" % "<version>"
libraryDependencies += "dev.zio" %% "zio-config-yaml" % "<version>" // for reading yaml configuration files
libraryDependencies += "dev.zio" %% "zio-config-magnolia" % "<version>" // for deriving configuration descriptions
```

Assume we have the following configuration file:

ConfigProvider.fromYamlString
```scala
import utils._
printSource("examples/shared/src/main/resources/application.yml")
```

## Xml String
We can read the configuration file as follows:

zio-config can read XML strings. Note that it's experimental with a dead simple native xml parser,
Currently it cannot XML comments, and has not been tested with complex data types, which will be fixed in the near future.
```scala mdoc:passthrough
import utils._
printSource("examples/shared/src/main/scala/zio/config/examples/configsources/YamlConfigReaderExample.scala")
```

```scala
import zio.config.xml.experimental._
import zio.Config
Here is the output:

final case class Configuration(aws: Aws, database: Database)
```
bootstrapServers: List(localhost:9092, locathost:9094)
region: US
port: 100
```

object Configuration {
val config: Config[Configuration] =
Aws.config.nested("aws").zip(Database.config.nested("database")).to[Configuration].nested("config")
## XML

final case class Aws(region: String, account: String)
ZIO Config can read XML strings using the `zio-config-yaml` module, so we have to add the following line to our `build.sbt` file:

object Aws {
val config: Config[Aws] = Config.string("region").zip(Config.string("account")).to[Aws]
}
final case class Database(port: Int, url: String)
```scala
libraryDependencies += "dev.zio" %% "zio-config-yaml" % "@VERSION@"
```

object Database {
val config: Config[Database] = Config.int("port").zip(Config.string("url")).to[Database]
}
}
Note that it's experimental with a dead simple native xml parser,
Currently it cannot XML comments, and has not been tested with complex data types, which will be fixed in the near future.

val config =
s"""
|<config>
| <aws region="us-east" account="personal"></aws>
| <database port="123" url="some url"></database>
|</config>
|
|""".stripMargin
Assume we have the `application.xml` file in the `resources` directory:

val parsed = ConfigProvider.fromYamlString(config).load(Configuration.config)
```scala mdoc:passthrough
import utils._
printSource("examples/shared/src/main/resources/application.xml")
```

We can load the configuration file as follows:

```scala mdoc:passthrough
import utils._
printSource("examples/shared/src/main/scala/zio/config/examples/configsources/YamlConfigReaderExample.scala")
```

### Indexed Map, Array datatype, and a some implementation notes
## Indexed Map, Array datatype, and a some implementation notes

`zio-config` comes up with the idea of `IndexedFlat` allowing you to define indexed configs (see examples below).
However, the constructors of `IndexedFlat` is not exposed to the user for the time being, since it can conflate with some ideas in `zio.core` `Flat`,
Expand All @@ -149,14 +142,15 @@ See https://github.com/zio/zio/pull/7823 and https://github.com/zio/zio/pull/789

These changes are to keep the backward compatibility of ZIO library itself.

#### What does it mean to users?
### What does it mean to users?
It implies, for sequence (or list) datatypes, you can use either `<nil>` or `""` to represent empty list in a flat structure.
See the below example where it tries to mix indexing into flat structure.
We recommend using `<nil>` over `""` whenever you are trying to represent a real indexed format

Example:

```scala
```scala mdoc:compile-only
import zio._
import zio.config._, magnolia._

final case class Department(name: String, block: Int)
Expand All @@ -175,17 +169,17 @@ val map =
"employees[1].departments" -> "<nil>",
)

ConfigProvider.fromMap(map).load(derivedConfig[Config])
ConfigProvider.fromMap(map).load(deriveConfig[Config])
```

Although we support indexing within Flat, formats such as Json/HOCON/XML is far better to work with indexing,
and zio-config supports these formats making use of the above idea.


#### Another simple example of an indexed format

```scala
### Another simple example of an indexed format

```scala mdoc:compile-only
import zio._
import zio.config._, magnolia._

final case class Employee(age: Int, name: String)
Expand Down
5 changes: 5 additions & 0 deletions examples/shared/src/main/resources/application.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"port": "123",
"url": "bla",
"region": "useast"
}
3 changes: 3 additions & 0 deletions examples/shared/src/main/resources/application.simple.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
port=123
url=bla
region=useast
4 changes: 4 additions & 0 deletions examples/shared/src/main/resources/application.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<config>
<aws region="us-east" account="personal"></aws>
<database port="123" url="some url"></database>
</config>

0 comments on commit 62116f9

Please sign in to comment.