Как отфильтровать результаты массива JSON по условию? - PullRequest
2 голосов
/ 12 июня 2019

Я использую Scala Play 2.7.2 и прочитал ScalaJsonTransformers и ScalaJson .После вызова JSON API я получаю (упрощенный MCVE) результат, подобный этому:

{
  "type": "searchset",
  "total": 5,
  "entry": [
    {
        "start": "2019-06-07T09:00:00",
        "end": "2019-06-07T11:00:00",
        "id": "55"
    },
    {
        "start": "2019-06-07T13:00:00",
        "end": "2019-06-07T15:00:00",
        "id": "56"
    },
    {
        "start": "2019-06-07T16:00:00",
        "end": "2019-06-07T17:00:00",
        "id": "60"
    },
    {
        "start": "2019-06-10T11:00:00",
        "end": "2019-06-10T12:00:00",
        "id": "58"
    },
    {
        "start": "2019-06-11T14:00:00",
        "end": "2019-06-11T15:00:00",
        "id": "61"
    }
  ]
}

, и я хотел бы отфильтровать результаты и выбрать только те, которые удовлетворяют условию, например, отфильтроватьте, чья конечная дата больше определенной даты val to = new DateTime("2019-06-10T00:00:00") и что-то делают alla:

(json \\ "end").filter(new DateTime(_).isBefore(to.toDate.getTime))...

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

Решение должно вывести результат:

{
  "type": "searchset",
  "total": 3,
  "entry": [
    {
        "start": "2019-06-07T09:00:00",
        "end": "2019-06-07T11:00:00",
        "id": "55"
    },
    {
        "start": "2019-06-07T13:00:00",
        "end": "2019-06-07T15:00:00",
        "id": "56"
    },
    {
        "start": "2019-06-07T16:00:00",
        "end": "2019-06-07T17:00:00",
        "id": "60"
    }
}

Как это можно сделать с помощью Play JSON?

1 Ответ

2 голосов
/ 12 июня 2019

Для проектирования от побережья к побережью попробуйте определить обновляющий трансформатор , например,

val to = new DateTime("2019-06-10T00:00:00")

val endDateFilterTransformer = (__ \ 'entry).json.update(__.read[JsArray].map {
  case JsArray(values) => JsArray(values.filter(v => (v \ "end").as[DateTime].isBefore(to)))
})

val outJson = json.transform(endDateFilterTransformer)
println(outJson.get)

который выводит

{
  "entry": [
    {
      "start": "2019-06-07T09:00:00",
      "end": "2019-06-07T11:00:00",
      "id": "55"
    },
    {
      "start": "2019-06-07T13:00:00",
      "end": "2019-06-07T15:00:00",
      "id": "56"
    },
    {
      "start": "2019-06-07T16:00:00",
      "end": "2019-06-07T17:00:00",
      "id": "60"
    }
  ],
  "total": 5,
  "type": "searchset"
}

В качестве альтернативы для JSON to OO, попробуйте десериализовать модель

case class Entry(start: DateTime, end: DateTime, id: String)
object Entry {
  implicit val format = Json.format[Entry]
}
case class Record(`type`: String, total: Int, entry: List[Entry])

object Record {
  implicit val format = Json.format[Record]
}

затем отфильтруйте, используя обычные методы Scala

val to = new DateTime("2019-06-10T00:00:00")
val record = Json.parse(raw).as[Record]
val filteredRecord = record.copy(entry = record.entry.filter(_.end.isBefore(to)))

затем десериализовать обратно в json следующим образом:

Json.toJson(filteredRecord)

который выводит

{
  "type": "searchset",
  "total": 5,
  "entry": [
    {
      "start": "2019-06-07T09:00:00.000+01:00",
      "end": "2019-06-07T11:00:00.000+01:00",
      "id": "55"
    },
    {
      "start": "2019-06-07T13:00:00.000+01:00",
      "end": "2019-06-07T15:00:00.000+01:00",
      "id": "56"
    },
    {
      "start": "2019-06-07T16:00:00.000+01:00",
      "end": "2019-06-07T17:00:00.000+01:00",
      "id": "60"
    }
  ]
}

где мы используем play-json-joda для DateTime сериализации

libraryDependencies += "com.typesafe.play" %% "play-json-joda" % "2.7.3"
import play.api.libs.json.JodaWrites._
import play.api.libs.json.JodaReads._
...