Reputation: 101
i am trying to extract aid and event_type from Option[String] what is the best scala way to extract those values and if not there get null as output.
val payload = Some({"event":"testApi",
"data":[{"aid":"test","pr":"{\"id\":\"813da0e5-d9aa-4275-b9d4-5e84362b73bb\",\"event_type\":\"promo app loaded\",\"label\":\"beach apartheid\",\"total\":1,\"timestamp\":1617891494152}}]",
"tv":"js-2.17.3"
})
If I have this how to extract other then if else.
Upvotes: 1
Views: 3954
Reputation: 40500
It depends on what it is you are going to do with this payload afterwards. Option
is a monad, and all the standard operations like .map
, flatMap
, .foreach
, .filter
, .collect
etc. apply to it. I really recommend that you read up on scala monads to get a good handle on it.
In a nutshell, you should structure your code so that you never need to do option.get
to access the actual value, almost never do option.isEmpty
(or option.nonEmpty
, and very rarely if ever do .getOrElse
(e.g. val unwrappedJson = payload.getOrElse('{}')
).
I would also avoid pattern matching in most cases, despite what that book mentioned in the other answer suggests. It may be "most common", but is not "the best" in most cases (though, this is starting to get into the "personal taste" area, there is nothing technically wrong with pattern matching, except that it is not "monadic" and is therefore somewhat harder to read and parse visually).
Some examples of things you can do:
def parsePayload(maybePayload: Option[String]): Option[Payload] =
maybePayload.map(json.readValue[Payload])
...
def getLabels(maybePayload: Option[String]): Seq[String] = maybePayload
.map(json.readValue[Payload])
.toSeq
.flatMap(_.data)
.map(_.pr.label)
...
def uniqueIds(maybePayload: Option[String]): Seq[String] = maybePayload
.map(json.readValue[Payload])
.toSeq
.flatMap(_.data)
.map(_.pr.id)
.distinct
...
def maybeData(maybePayload: Option[String]): Seq[Data] =
parsePayload(maybePayload)
.fold(Seq.empty[Data])(_.data)
...
def byId(maybePayload: Option[String]): Map[String, Seq[Data]] = maybePayload
.map(json.readValue[Payload])
.toSeq
.flatMap(_.data)
.groupBy(_.pr.id)
.map { case(id, datas) => datas }
def forId(maybePayload: Option[String], id: String): Seq[Data] = maybePayload
.map(json.readValue[Payload])
.toSeq
.flatMap(_.data.filter(_.pr.id == id))
...
def forId2(maybePayload: Option[String], id: String): Seq[Data] =
byId(maybePayload).getOrElse(id)
...
def maxTotal(maybePayload: Option[String]): Option((String, Int)) =
parsePayload(maybePayload)
.collect { case Payload(_, data, _) if data.nonEmpty => data.maxBy(_.pr.total) }
.map { case data => data.pr.id -> data.pr.total }
...
def printPayload(maybePayload: Option[String]): Unit =
maybePayload.foreach(println)
Etc.
Upvotes: 4
Reputation: 18475
According to the book "Programming in Scala, 3rd Edition", published by artima it says:
"The most common way to take optional values apart is through a pattern match."
Example:
def show(x: Option[String]): String = x match {
case Some(s) => s
case None => "?"
}
Upvotes: 1