Soheil Pourbafrani
Soheil Pourbafrani

Reputation: 3427

Scala get JSON value in a specific data type on map object

Using jackson library I read json data from a file (each row of file is a JSON object) an parse it to a map object of String and Any. My goal is to save specified keys (id and text) to a collection.

val input = scala.io.Source.fromFile("data.json").getLines()
val mapper = new ObjectMapper() with DefaultScalaModule
val data_collection = mutable.HashMap.empty[Int, String]

for (i <- input){
      val parsedJson = mapper.readValue[Map[String, Any]](i)
      data_collection.put(
        parsedJson.get("id"),
        parsedJson.get("text")
      )

But as the values in the parsedJson map have the Any type, getting some keys like id and text, it returns Some(value) not just the value with the appropriate type. I expect the values for the id key to be Integer and values for the text to be String. Running the code I got the error:

Error:(31, 23) type mismatch;
 found   : Option[Any]
 required: Int
        parsedJson.get("id"),

Here is a sample of JSON data in the file:

{"text": "Hello How are you", "id": 1}

Is it possible in Scala to parse id values to Int and text values to String, or at least convert Some(value) to value with type Int or String?

Upvotes: 0

Views: 2780

Answers (2)

If you want to get a plain value from a Map instead of a Option you can use the () (apply) method - However it will throw an exception if the key is not found.

Second, Scala type system is static not dynamic, if you have an Any that's it, it won't change to Int or String at runtime, and the compiler will fail - Nevertheless, you can cast them using the asInstanceOf[T] method, but again if type can't be casted to the target type it will throw an exception.

Please note that even if you can make your code work with the above tricks, that code wouldn't be what you would expect in Scala. There are ways to make the code more typesafe (like pattern matching), but parsing a Json to a typesafe object is an old problem, I'm sure jackson provides a way to parse a json into case class that represent your data. If not take a look to circe it does.

Upvotes: 2

Amit Prasad
Amit Prasad

Reputation: 725

Try the below code :

import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.module.scala.DefaultScalaModule
import 
 com.fasterxml.jackson.module.scala.experimental.ScalaObjectMapper

val input = scala.io.Source.fromFile("data.json").getLines() 
val mapper = new ObjectMapper() with ScalaObjectMapper
mapper.registerModule(DefaultScalaModule)
val obj = mapper.readValue[Map[String, Any]](input)
val data_collection = mutable.HashMap.empty[Int, String]
for (i <- c) {
data_collection.put(
  obj.get("id").fold(0)(_.toString.toInt),
  obj.get("text").fold("")(_.toString)
 )
 }
println(data_collection) // Map(1 -> Hello How are you)

Upvotes: 2

Related Questions