Search code examples
jsonscalaapache-sparkscala-breeze

Scala JSON to DenseMatrix


I am trying to convert this JSON response:

[
   {  
      "metric":"energy.salted",
      "tags":{  
         "sensor":"0",
         "unit":"101"
      },
      "aggregateTags":[  

      ],
      "dps":{  
         "1477958400":1.9519165754318237,
         "1477958401":-0.4030894637107849,
         "1477958402":0.6892277598381042,
         "1477958403":3.0232467651367188,
         "1477958404":0.07003471255302429,
         "1477958405":2.305912971496582
      }
   },
   {  
      "metric":"energy.salted",
      "tags":{  
         "sensor":"1",
         "unit":"101"
      },
      "aggregateTags":[  

      ],
      "dps":{  
         "1477958400":4.979776382446289,
         "1477958401":1.8036608695983887,
         "1477958402":3.0569913387298584,
         "1477958403":0.8318896889686584,
         "1477958404":-0.3151852488517761,
         "1477958405":2.563884735107422
      }
   }
]

Into a DenseMatrix of the values associated with the "dps" keys. The final DenseMatrix should look like this:

[
    [1.9519165754318237, -0.4030894637107849, 0.6892277598381042, 3.0232467651367188, 0.07003471255302429, 2.305912971496582],
    [4.979776382446289, 1.8036608695983887, 3.0569913387298584, 0.8318896889686584, -0.3151852488517761, 2.563884735107422]
]

I have parsed the JSON using play.api.libs.json.JSON, and I can even extract the "dps" values using:

jsonResponse = Json.parse(response.body)
for (i <- 0 until numSensors) {
  dataMap = (jsonResponse.apply(i) \ "dps")
}

But how do I convert it to a dense matrix with the above format?


Solution

  • Assume you have same keys for all dps, you can try this, create an empty DenseMatrix and bind each array to the matrix with DenseMatrix.vertcat:

    val keys = List("1477958400", "1477958401", "1477958402", "1477958403", "1477958404", "1477958405")
    
    var mat = new DenseMatrix[Double](0, 6, Array.empty[Double])
    
    for (i <- 0 until numSensors) {
    
        val dataMap = (jsonResponse.apply(i) \ "dps")
        val array = keys.map(key => (dataMap \ key).as[Double]).toArray
    
        mat = DenseMatrix.vertcat(mat, new DenseMatrix[Double](1, 6, array))   
    }
    
    mat
    
    //breeze.linalg.DenseMatrix[Double] = 1.9519165754318237  -0.4030894637107849  0.6892277598381042  ... (6 total)
    //                                    4.979776382446289   1.8036608695983887   3.0569913387298584  ...