Scala JSON 将嵌套数组解析为案例类

时间:2021-06-28 15:18:01

标签: json scala apache-spark

我正在使用标准的 Scala json 解析,但遇到了嵌套数组的问题。

这是示例 JSON:

{
    "_id": "id_here",
    "_rev": "rev_here",
    "RandomHosts": [
        "randomhosts_1",
        "randomhosts_2",
        "randomhosts_3",
        "randomhosts_4"
    ],
    "FirstObject": {
        "Host": "ActualHost",
        "Port": 8888,
        "DB": 0,
        "WFMDB": 1,
        "ETLDB": 2,
        "HostListPrefix": "Dev1",
        "ExtraHostsBands": [
            {
                "Host": "dev2",
                "Port": 2222,
                "DB": 0,
                "WFMDB": 1,
                "ETLDB": 2,
                "HostListPrefix": "Dev2"
            },
            {
                "Host": "dev3",
                "Port": 3333,
                "DB": 0,
                "WFMDB": 1,
                "ETLDB": 3,
                "HostListPrefix": "Dev3"
            }
        ],
        "RandomObject":{}
    }
}
// I HAVE OTHER IMPORTS AS WELL
import scala.util.parsing.json._;

case class BandClass (
        Host: String,
        Port:Int,
        DB:Int,
        WFMDB:Int,
        ETLDB:Int,
        HostListPrefix:String
    );

var jsonString = "<myjson>";

val bandconfig = JSON.parseFull(jsonString);
// THIS WORKS PERFECT AND GIVES ME JOINED STRING
val random_hosts = bandconfig.get.asInstanceOf[Map[String, Any]]("RandomHosts").asInstanceOf[List[String]].mkString(",");

//THIS ALSO WORKS PERFECT AND GIVES ME HOST AND PORT
val firstObject = bandconfig.get.asInstanceOf[Map[String, Any]]("FirstObject").asInstanceOf[Map[String, Any]];
val firstObjectHost = firstObject("Host").asInstanceOf[String]
val firstObjectPort = firstObject("Port").asInstanceOf[Double].toInt

//THIS IS WHERE EVERYTHING FALLS APART
val extraBands = firstObject("ExtraHostBands").asInstanceOf[List[BandClass]]

//EVEN THIS DOESNT WORK
val extraBands2 = firstObject("ExtraHostBands").asInstanceOf[Map[String, Any]]

Caused by: java.lang.ClassCastException: scala.collection.immutable.HashMap$HashTrieMap cannot be cast to $BandClass

我不确定如何将嵌套的 json 数组强制添加到我的案例类中。我什至选择了 map 或 seq 或任何我可以迭代的东西,以从 ExtraHostBand json 对象中获取主机/端口。

任何人都可以指出我正确的方向以将该 json 数组放入 case 类吗?我也可以访问 play-json,但似乎也无法弄清楚。

1 个答案:

答案 0 :(得分:0)

最终使用 play-json 并且效果非常好。这是一个解决方案,以防将来有人需要它:

import play.api.libs.json.Json;
import play.api.libs.json;
import play.api.libs.json.Writes;
import play.api.libs.json._;
import play.api.libs._;
import play.api.libs.functional.syntax._;
import play.api.libs.json.Reads._;


case class BandClass (
        Host: String,
        Port:Int,
        DB:Int,
        WFMDB:Int,
        ETLDB:Int,
        HostListPrefix:String
    )

    case class FirstObject (
        Host: String,
        Port:Int,
        DB:Int,
        WFMDB:Int,
        ETLDB:Int,
        HostListPrefix:String,
        ExtraHostsBands: List[BandClass]
    )

    case class RawConfig (
        _id: String,
        _rev: String,
        RandomHosts: List[String],
        FirstObject: FirstObject
    )

    implicit val bandClassFormat = Json.format[BandClass];
    implicit val firstObjectFormat = Json.format[FirstObject];
    implicit val rawConfigFormat = Json.format[RawConfig];


    val playJsonParse = Json.parse(<myjson>).as[RawConfig]; 
    println("playJSON ID " + playJsonParse._id)
    println("playJSON REV " + playJsonParse._rev)

    playJsonParse.FirstObject.ExtraHostBands.foreach
        {
            case(r) => {
                println("Host " + r.Host);
                println("Host Prefix " + r.HostListPrefix);
                println("ETLDB " + r.ETLDB);
            }
        }