首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用play-json忽略空对象?

如何使用play-json忽略空对象?
EN

Stack Overflow用户
提问于 2018-11-22 03:01:58
回答 1查看 621关注 0票数 0

我是Scala和函数式编程的新手,所以这个问题可能有一个非常简单的答案。然而,我不能弄清楚,所以它是这样的:

我有一个case类层次结构,它表示编译器中的抽象语法树。在某种程度上,我有一个List[Statement]形式的语句列表。这将使用Json对象数组进行序列化,其中每个对象表示一条语句。但是,某些类型的语句是多余的,所以我不想序列化它们。例如,返回void。下面的代码有望阐明这一点:

代码语言:javascript
复制
sealed trait Statement

sealed trait Expression

case object Empty extends Expression

case class Return(e: Expression) extends Statement

我想要的是根本不序列化Return(空)。现在我得到了一些类似的东西:

代码语言:javascript
复制
"Return": {}

我怎么能忽略Return(Empty)呢?为了让它更通用。我不想在我的json中有像{}那样的空对象。我如何才能确保它们不会到达我的json?

以下是我到目前为止尝试过的方法(但没有成功):

代码语言:javascript
复制
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)))
}

也许上面的技术是有效的,但出于某种原因,据我所知,它甚至一开始都没有被调用。

EN

回答 1

Stack Overflow用户

发布于 2018-11-22 15:29:54

在这种情况下你应该小心,因为你有封闭的特征,所以你应该以一种有组织的方式工作。

让我们把问题分成几个小问题,假设你只想把你的对象写到json中。然后我们就可以解决删除空对象的问题了。

我添加了更多的类来澄清这个概念:

代码语言:javascript
复制
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

第一步(为表达式提供编写器):

要做到这一点,你必须为EmptyNonEmptyExpression创建编写器,所以我们可以这样做:

代码语言:javascript
复制
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)
    }
  }
}

第二步(为语句提供编写器):

你必须为ReturnNoReturn提供编写器。请注意,play能够知道如何为Return创建编写器,并且它有Expression,因为我将expressionWriter定义为implicit。所以它现在知道如何序列化Expression了。

代码语言:javascript
复制
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)
    }
  }
}

让我们测试一下,以确保它工作正常:

代码语言:javascript
复制
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":{}}

最后一步(创建不带空的列表写入器):

代码语言:javascript
复制
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))
  }
}

让我们试一下:

代码语言:javascript
复制
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}}

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53418925

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档