我是Scala和函数式编程的新手,所以这个问题可能有一个非常简单的答案。但是,我无法弄清楚,所以在这里:
我有一个案例类层次结构,它表示编译器中的抽象语法树。在某个时候,我有List[Statement]
形式的语句列表。这将使用对象的Json数组进行序列化,其中每个对象代表一条语句。但是,某些类型的语句是多余的,因此我不想序列化它们。例如,返回void。以下代码有望澄清这一点:
sealed trait Statement
sealed trait Expression
case object Empty extends Expression
case class Return(e: Expression) extends Statement
我想要的是根本不序列化Return(Empty)。现在我得到类似的东西:
"Return": {}
如何简单地忽略Return(Empty)
?
使它更通用。我不想像{}
这样的json中有空对象。我如何确定他们没有将其添加到我的json中?
这是我到目前为止尝试过的(但没有成功):
implicit val statementListWrites = StatementListWrites
object StatementListWrites extends Writes[List[Statement]] {
override def writes(stms: List[Statement]) =
JsArray(stms.filter(stm => {
stm match {
case Return(Empty) => false
case _ => true
}
}).map(s => Json.toJson(s)))
}
也许上述技术可行,但由于某种原因,据我所知,甚至还没有开始。
答案 0 :(得分:0)
在这种情况下,您应该小心,因为您具有封闭的特质,因此您应该有条理地工作。
让我们将问题分解为较小的问题,假设您只想将对象写入json。那么我们就可以解决删除空对象的问题。
我添加了更多的类来澄清这个想法:
sealed trait Expression
case object Empty extends Expression
case class NonEmptyExpression(x: Int) extends Expression
sealed trait Statement
case class Return(e: Expression) extends Statement
case class NoReturn(x: Int) extends Statement
第一步(提供Expresion的作者):
要执行此操作,您必须为Empty
和NonEmptyExpression
创建作家,因此我们可以通过以下方式做到这一点:
val emptyExpressionWrites = new Writes[Empty.type] {
override def writes(e: Empty.type) = Json.obj()
}
val nonEmptyExpressionWrites = Json.writes[NonEmptyExpression]
implicit val expressionWrites = new Writes[Expression] {
override def writes(exp: Expression) = {
exp match {
case Empty => emptyExpressionWrites.writes(Empty)
case nonEmptyExpression: NonEmptyExpression => nonEmptyExpressionWrites.writes(nonEmptyExpression)
}
}
}
第二步(声明的提供者):
您必须提供Return
和NoReturn
的作家。请注意,因为我将Return
定义为Expression
,所以play能够知道如何为expressionWriter
创建作者,并且它具有implicit
。因此它知道如何立即序列化Expression
。
val returnWrites = Json.writes[Return]
val noReturnWrites = Json.writes[NoReturn]
val statementWrites = new Writes[Statement] {
override def writes(s: Statement) = {
s match {
case r: Return => returnWrites.writes(r)
case nr: NoReturn => noReturnWrites.writes(nr)
}
}
}
让我们对其进行测试以确保其工作正常:
val statementWithNonEmpty = Return(NonEmptyExpression(100))
println(s"statementWithNonEmpty Json: ${statementWrites.writes(statementWithNonEmpty).toString()}")
val statementWithEmpty = Return(Empty)
println(s"statementWithEmpty Json: ${statementWrites.writes(statementWithEmpty).toString()}")
输出为:
statementWithNonEmpty Json:{“ e”:{“ x”:100}}
statementWithEmpty Json:{“ e”:{}}
最终步骤(创建没有空白的列表编写器):
val listStatementWrites = new Writes[Seq[Statement]] {
override def writes(o: Seq[Statement]) = {
val listWithoutEmpty = o.filter {
case Return(Empty) => false
case _ => true
}
JsArray(listWithoutEmpty.map(statementWrites.writes))
}
}
让我们尝试一下:
val listOfStatements = List(Return(NonEmptyExpression(100)), Return(Empty), Return(NonEmptyExpression(200)))
println(s"listOfStatements: ${listStatementWrites.writes(listOfStatements).toString()}")
输出为:
listOfStatements:[{“ e”:{“ x”:100}},{“ e”:{“ x”:200}}]