Skip to content

Commit

Permalink
Updating Decoding doc with example of writing custom decoder
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremycod committed Apr 14, 2024
1 parent b9cab26 commit 0609539
Showing 1 changed file with 38 additions and 0 deletions.
38 changes: 38 additions & 0 deletions docs/decoding.md
Original file line number Diff line number Diff line change
Expand Up @@ -174,3 +174,41 @@ implicit val decodeName: JsonDecoder[String Refined NonEmpty] =
```

Now the code compiles.

### Writing a Custom Decoder
In some rare cases, you might encounter situations where the data format deviates from the expected structure.

#### Problem
Let's consider a Fruit case class with a categories field that should be a list of strings. However, some JSON data might represent the categories as a comma-separated string instead of a proper list.

```scala mdoc
case class Fruit(name: String, categories: List[String])

"""{"name": "Banana", "categories": "Fruit,Berries"}""".fromJson[Fruit]
"""{"name": "Orange", "categories": ["Fruit", "Citrus"]}""".fromJson[Fruit]
```

#### The Solution: Custom Decoder

We can create custom decoders to handle specific data formats. Here's an implementation for our Fruit case class:
```scala mdoc
implicit val decoder: JsonDecoder[Fruit] = JsonDecoder[Json].mapOrFail {
case Json.Obj(fields) =>
(for {
name <- fields.find(_._1 == "name").map(_._2.toString())
categories <- fields
.find(_._1 == "categories").map(_._2.toString())
} yield Right(Fruit(name, handleCategories(categories))))
.getOrElse(Left("DecodingError"))
case _ => Left("Error")
}

private def handleCategories(categories: String): List[String] = {
val decodedList = JsonDecoder[List[String]].decodeJson(categories)
decodedList match {
case Right(list) => list
case Left(_) =>
categories.replaceAll("\"", "").split(",").toList
}
}
```

0 comments on commit 0609539

Please sign in to comment.