Если вы хотите избежать причудливых трюков, и у вас не слишком много общих классов, чтобы написать это, вы можете просто написать методы для создания карт самостоятельно. Я бы предложил добавить методы, названные как toMap
, к вашим классам case. OutlierPortalTimeSeriesData
«s прост, если вы используете Map()
конструктор:
case class OutlierPortalTimeSeriesData(period: Timestamp, totalAmount: Double, isOutlier: Int) {
def toMap: Map[String, Any] = Map(
"period" -> period,
"totalAmount" -> totalAmount,
"isOutlier" -> isOutlier)
}
Я предполагаю, что есть некоторое дублирование существует, но, по крайней мере, если вы когда-либо есть причина для изменения значений строк, но не имена переменных, у вас есть возможность для этого.
Для того, чтобы последовательность то, что вы можете позвонить toMap
дальше, и превратить его в Seq[Map[String, Any]]
, просто использовать map
:
mySeq.map { _.toMap }
Мы можем использовать это как писать OutlierPortal
«s toMap
:
case class OutlierPortal(portal: String, timeData: Seq[OutlierPortalTimeSeriesData]) {
def toMap: Map[String, Any] = Map(
"portal" -> portal,
"timeData" -> timeData.map { _.toMap })
}
, а затем еще раз для преобразования Seq[OutlierPortal]
в Seq[Map[String, Any]]
.
В зависимости от того, как вы используете эти объекты и методы, вы можете определить черту, отличающую классы с помощью этого метода, и ваши классы случае продлить его:
trait HasToMap { def toMap: Map[String, Any] }
case class Blah(/* ... */) extends HasToMap {
def toMap: /* ... */ }
}
Это позволит вам принять значение, которое, как вы знаете, можно преобразовать в Map[String, Any]
(или их последовательность и т. д.) в методе, который в противном случае не заботится о том, какой именно тип он есть.
Чтобы быть ясным, вы хотите избежать жесткого кодирования строк? –
Гибкие клавиши были бы хорошими, но не обязательными. –
Вы хотите, чтобы 'значение' типа' Any' содержало значение полей? –