Как я могу игнорировать пустые объекты с помощью play-json? - PullRequest
0 голосов
/ 21 ноября 2018

Я новичок в 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 (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)))
}

Возможно, описанная выше техника работаетно по какой-то причине он даже не вызван, насколько я понимаю.

1 Ответ

0 голосов
/ 22 ноября 2018

Вы должны быть осторожны в таких случаях, потому что у вас есть запечатанные черты, поэтому вы должны работать организованно.

Давайте разделим проблему на более мелкие проблемы, Предположим, что вы просто хотите записать свои объекты в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)
    }
  }
}

Второй шаг (предоставить писателя для Statement):

Вы должны предоставить писателя для 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}}]

...