我是Scala和函数式编程的新手,所以这个问题可能有一个非常简单的答案。然而,我不能弄清楚,所以它是这样的:
我有一个case类层次结构,它表示编译器中的抽象语法树。在某种程度上,我有一个List[Statement]形式的语句列表。这将使用Json对象数组进行序列化,其中每个对象表示一条语句。但是,某些类型的语句是多余的,所以我不想序列化它们。例如,返回void。下面的代码有望阐明这一点:
sealed trait Statement
sealed trait Expression
case object Empty extends Expression
case class Return(e: Expression) extends Statement我想要的是根本不序列化Return(空)。现在我得到了一些类似的东西:
"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)))
}也许上面的技术是有效的,但出于某种原因,据我所知,它甚至一开始都没有被调用。
发布于 2018-11-22 15:29:54
在这种情况下你应该小心,因为你有封闭的特征,所以你应该以一种有组织的方式工作。
让我们把问题分成几个小问题,假设你只想把你的对象写到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第一步(为表达式提供编写器):
要做到这一点,你必须为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提供编写器。请注意,play能够知道如何为Return创建编写器,并且它有Expression,因为我将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}}
https://stackoverflow.com/questions/53418925
复制相似问题