如何将JsValue序列存储到ArrayBuffer中

时间:2015-06-24 11:16:40

标签: json scala playframework

我有以下json对象包含json对象列表。这些对象中的每一个都包含有关工作站对象的信息。

"stations": [
            {
                "cryptName": "Tv_Gara Nord 1",
                "easyName": "Gara de Nord",
                "lat": 45.750287,
                "lng": 21.207498
            },
            {
                "cryptName": "Tv_R Carol 1",
                "easyName": "Regele Carol I",
                "lat": 45.745068,
                "lng": 21.211034
            },
            {
                "cryptName": "Tv_Mocioni 1",
                "easyName": "Piata Mocioni (Sinaia)",
                "lat": 45.746343,
                "lng": 21.21551
            }]

我已经尝试了这个,我无法将其转换为格式为的ArrayBuffer:

ArrayBuffer(List(" cryptName"," easyName"," lat"," lng"),...)

[第73行.. 77] 问题在于(js \\\ "cryptName")(0) ... (js \\\ "lng")(0)

如何将所有这些非单一电台正确存储到我的ArrayBuffer中?

    package backend

    import scala.concurrent.duration._
    import scala.collection.immutable.Seq
    import scala.concurrent.forkjoin.ThreadLocalRandom
    import akka.actor.{ ActorRef, Props }
    import play.api.libs.json.Json
    import play.extras.geojson.{ LineString, LatLng, FeatureCollection }
    import play.api.Logger
    import actors.GeoJsonBot
    import java.net.URL
    import akka.actor.Actor
    import scala.io.Source
    import akka.cluster.Cluster
    import play.api.libs.json.JsValue
    import org.apache.commons.lang3.Validate

    object BotManager
    {
        def props(regionManagerClient: ActorRef, data: Seq[URL]): Props = Props(new BotManager(regionManagerClient, data))
        private case object Tick
    }

    /**
     * Loads and starts GeoJSON bots
     */
     class BotManager(regionManagerClient: ActorRef, data: Seq[URL]) extends Actor
    {
        import BotManager._

        var total = 0
    val max = Settings(context.system).TotalNumberOfBots

    import context.dispatcher
    val tickTask = context.system.scheduler.schedule(1.seconds, 3.seconds, self, Tick)
    val port = Cluster(context.system).selfAddress.port.get

    override def postStop(): Unit = tickTask.cancel()

    def receive =
    {
        case Tick if total >= max => tickTask.cancel()
        case Tick =>
            val totalBefore = total
            val originalTrail = total == 0
            println("NODE: " + data)
            data.zipWithIndex.foreach
            {
                case (url, id) =>
                    val json = Json.parse(Source.fromURL(url).mkString)
                    println("URL: " + url + "ID: " + id)
                    Json.fromJson[FeatureCollection[LatLng]](json).fold(
                    {
                        invalid =>
                        Logger.error("Error loading geojson bot: " + invalid)
                    }, valid => valid.features.zipWithIndex.map
                    {
                        feature => feature._1.geometry match
                        {
                            case route: LineString[LatLng] if total < max => total += 1
                            val userId = "bot-" + total + "-" + port + "-" + id + "-" + feature._1.id.getOrElse(feature._2) + "-" + feature._1.properties.flatMap(js => (js \ "name").asOpt[String]).getOrElse("") + feature._1.properties.flatMap(js => (js \ "segment").asOpt[String]).getOrElse("")
                            val stations = feature._1.properties.flatMap(js => (js \ "stations").asOpt[JsValue])

                            import play.api.libs.json.JsObject
                            import play.api.libs.json.JsArray
                            var stationss = feature._1.properties.flatMap(js => (js \ "stations").asOpt[JsValue])
                            val crypt = stationss.flatMap(js => (js \\ "cryptName")(0).asOpt[JsValue])
                            val ename = stationss.flatMap(js => (js \\ "easyName")(0).asOpt[JsValue])
                            val lat   = stationss.flatMap(js => (js \\ "lat")(0).asOpt[JsValue])
                            val lng   = stationss.flatMap(js => (js \\ "lng")(0).asOpt[JsValue])

                            case class Station(cryptName: String, easyName: String, lat: Float, lng: Float)
                            implicit val readsStation = Json.reads[Station]
                            case class Stations(stations: List[Station])
                            implicit val readsStations = Json.reads[Stations]

                            val stations = Json.parse(text).as[Stations].stations.map(s => List(s.cryptName, s.easyName, s.lat, s.lng)).to[ArrayBuffer]

                            println("List: [" + crypt.get + ", " + ename.get + ", " + lat.get + ", " + lng.get + "]")

                            val offset =
                                if (originalTrail) (0.0, 0.0)
                                else (ThreadLocalRandom.current.nextDouble() * 15.0,
                            ThreadLocalRandom.current.nextDouble() * -30.0)
                            context.actorOf(GeoJsonBot.props(route, stations, offset, userId, regionManagerClient))
                            case other =>
                        }
                    })
            }

            println("Started " + (total - totalBefore) + " bots, total " + total)
    }
}

2 个答案:

答案 0 :(得分:2)

我会这样做:

case class Station(cryptName: String, easyName: String, lat: Float, lng: Float)
implicit val readsStation = Json.reads[Station]
case class Stations(stations: List[Station])
implicit val readsStations = Json.reads[Stations]

(假设JSON为{ stations: [ ... ] }

然后使用以下内容:

val stations = Json.parse(text).as[Stations].stations
    .map(s => List(s.cryptName, s.easyName, s.lat, s.lng)).to[ArrayBuffer])

将生成以下内容(给出您的样本):

ArrayBuffer(List(Tv_Gara Nord 1, Gara de Nord, 45.750286, 21.207499), List(Tv_R Carol 1, Regele Carol I, 45.745068, 21.211035), List(Tv_Mocioni 1, Piata Mocioni (Sinaia), 45.74634, 21.21551))

答案 1 :(得分:1)

使用Reads\Writes宏。

创建案例类,例如

case class Station(cryptName: String, easyName: String, lat: String, long: String)
case class Stations(stations: Seq[Station])

创建阅读,

import play.api.libs.json._
import play.api.libs.functional.syntax._

implicit val stationReads = Json.reads[Station]
implicit val stationsReads = Json.reads[Stations]

做转换,

val json: JsValue = Json.parse(jsonString)
Json.fromJson[Stations](json) match {
  case JsSuccess(t, _) => ???
  case any: JsError    => ???
}

浏览read/write combinatorsread/write macros