Spray-json convert part of the json to Map[String,List[Double]]

4.5k views Asked by At

I have the following json

   {  
       "op":{  
          "samples":{  
             "ep_mem_high_wat":[  0,0,0,0,0,0,0],
             "ep_mem_low_wat":[  0,0,0,0,0,0,0]
          },
          "samplesCount":60,
          "isPersistent":true,
          "lastTStamp":1415619627689,
          "interval":1000
       },
       "hot_keys":[  
          {  
             "name":"counter::F03E91E2A4B9C25F",
             "ops":0.11010372549516878
          }
       ]
    }

I would like to parse "samples" property of this Json as Map[String,List[Double]] as

Map[String,List[Double]]("ep_mem_high_wat" -> [ 0,0,0,0,0,0,0],"ep_mem_low_wat" -> [0,0,0,0,0,0,0])

For this purpose I perform the following: I create my case classes

  case class Samples(properties:Map[String,List[Double]])
  case class Op(samples:Samples,samplesCount:Int,isPersistent:Boolean,lastTStamp:Long,interval:Int)
  case class Key(name:String,ops:Double)
  case class BucketStatisticResponse(op:Op,hot_keys:List[Key])

and then I create custom Json protocol

 object BucketStatisticJsonProtocol extends DefaultJsonProtocol {

    implicit object SamplesJsonFormat extends RootJsonFormat[Samples] {

      def write(obj: Samples) = obj.toJson
      def read(value: JsValue) =  {
         val props = value.asJsObject.fields
          Samples(value.convertTo[Map[String,List[Double]]])
      }
    }
    implicit val keyFormat = jsonFormat2(Key)
    implicit val opFormat = jsonFormat5(Op)
    implicit val bucketStatisticFormat= jsonFormat2(BucketStatisticResponse)
  }

And then I'm trying to parse json

 import BucketStatisticJsonProtocol._
 val res =  json.toJson.convertTo[BucketStatisticResponse]

As the result I'm gettign the folloing exception:

Exception in thread "main" spray.json.DeserializationException: Object expected in field 'op'
    at spray.json.package$.deserializationError(package.scala:23)
    at spray.json.ProductFormats$class.fromField(ProductFormats.scala:54)
    at high.availability.poc.DynamicJson$BucketStatisticJsonProtocol$.fromField(DynamicJson.scala:23)

What am I doing wrong?

1

There are 1 answers

2
Alex Cruise On BEST ANSWER

Look at the error message: It's complaining about the type of value it's finding in the AST for the op field. So the document you're actually parsing probably doesn't match your sample above.

Other than that, your code looks OK to me. Just as a matter of taste, I typically don't extend DefaultJsonProtocol; I put my JSON formats in the package object, and import DefaultJsonProtocol._ to handle any of the simplistic conversions as necessary.