Search code examples
jsonscalaspray

matcherror exception while trying to convert Json string


I have following simple code

val fileLine = s"""{"AP_details":   [{"MAC_Address":    "00:11:74:00:00:00"},{"MAC_Address":    "00:11:74:00:00:00"},{"MAC_Address":    "00:11:74:00:00:00"}]}
    """  
  val jsonAst = fileLine.parseJson
  import APDetailsJsonProtocol._
  jsonAst.convertTo[APDetails]

The conversions are defined in another file as

package test import spray.json._ import DefaultJsonProtocol._

case class APDetails(val mAPRadioOperatingParams:List[APDetail])
case class APDetail(val mac_id:String)

object APDetailsJsonProtocol extends DefaultJsonProtocol {
  implicit val APDetailFormat = jsonFormat1(APDetail)
  implicit object APDetailsJsonFormat extends RootJsonFormat[APDetails] {    
    def write(c: APDetails) = ??? 
    def read(value: JsValue) = value.asJsObject.getFields("AP_Details") match 
    {            
      case Seq(jsv ) => new APDetails(jsv.convertTo[List[APDetail]])              
    }
  }
}

However I get the following exception

Exception in thread "main" scala.MatchError: Vector() (of class scala.collection.immutable.Vector)
    at test.APDetailsJsonProtocol$APDetailsJsonFormat$.read(APDetails.scala:13)
    at test.APDetailsJsonProtocol$APDetailsJsonFormat$.read(APDetails.scala:11)
    at spray.json.JsValue.convertTo(JsValue.scala:31)
    at test.bootStrap.<init>(bootStrap.scala:25)
    at test.TestApp$.delayedEndpoint$test$TestApp$1(TestApp.scala:10)
    at test.TestApp$delayedInit$body.apply(TestApp.scala:4)
    at scala.Function0$class.apply$mcV$sp(Function0.scala:34)
    at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:12)
    at scala.App$$anonfun$main$1.apply(App.scala:76)
    at scala.App$$anonfun$main$1.apply(App.scala:76)
    at scala.collection.immutable.List.foreach(List.scala:381)
    at scala.collection.generic.TraversableForwarder$class.foreach(TraversableForwarder.scala:35)
    at scala.App$class.main(App.scala:76)
    at test.TestApp$.main(TestApp.scala:4)
    at test.TestApp.main(TestApp.scala)

What am i doing wrong? best regards, Vishal


Solution

  • You have "AP_details" in your Json. And you are doing a getFields("AP_Details").

    Notice that small d in details and capital D in Details. Which results in an empty Vector. But you have not handled the case of empty vector thus your matching fails which gives you a match error.

    Now... once you remove this problem then you have another problem to take care of.

    So you have a,

    case class APDetail(val mac_id:String)
    

    And then you defined a JsonFormat for it like this,

    implicit val APDetailFormat = jsonFormat1(APDetail)
    

    Now... this will expect the Json to have the exact field name which is mac_id for each APDetail but your Json has MAC_Address. So this will not work for you.

    So you will have to first fix your case class (or provide an appropriate JsonFormat for it),

    case class APDetail(Mac_Address: String)
    

    Now... there is another problem in your read, It should be like this,

    def read(value: JsValue) = value.asJsObject.getFields("AP_details") match {            
      case Seq(jsv): Seq[JsArray] => new APDetails(jsv.convertTo[List[APDetail]])              
    }