1

I have a json string:

val message = "{\"me\":\"a\",
    \"version\":\"1.0\",
    \"message_metadata\": \"{
                          \"event_type\":\"UpdateName\",
                          \"start_date\":\"1515\"}\"
    }"

I want to extract the value of the field event_type from this json string. I have used below code to extract the value:

val mapper = new ObjectMapper
val root = mapper.readTree(message)
val metadata =root.at("/message_metadata").asText()
val root1 = mapper.readTree(metadata)
val event_type =root1.at("/event_type").asText()
print("eventType:" + event_type.toString) //UpdateName

This works fine and I get the value as UpdateName. But I when I want to get the event type in a single line as below:

val mapper = new ObjectMapper
val root = mapper.readTree(message)
val event_type =root.at("/message_metadata/event_type").asText()
print("eventType:" + event_type.toString) //Empty string

Here event type returns a empty sting. This might be because of the message_metadata has Json object as a string value. Is there a way I can get the value of event_type in a single line?

Jhutan Debnath
  • 505
  • 3
  • 13
  • 24

3 Answers3

1

The problem is that your JSON message contains an object who's message_metadata field itself contains JSON, so it must be decoded separately. I'd suggest that you don't put JSON into JSON but only encode the data structure once.

Example:

val message = "{\"me\":\"a\",
    \"version\":\"1.0\",
    \"message_metadata\": {
                          \"event_type\":\"UpdateName\",
                          \"start_date\":\"1515\"
    }
}"
Ulrich Eckhardt
  • 16,572
  • 3
  • 28
  • 55
  • This input json comes from an external service and can not change the format. Is there any other way to parse it and the value? – Jhutan Debnath Jan 07 '18 at 11:47
  • No, using the simple version you tried is impossible because the message format requires two steps for decoding, since it is JSON nested inside JSON. – Ulrich Eckhardt Jan 07 '18 at 11:58
  • Any other alternative approach? – Jhutan Debnath Jan 07 '18 at 12:01
  • Well, you do have a workaround there already. I don't see any other approach considering the structure of the message. I'd try to get the sender to change their format though, in particular since they themselves have the same issue because they need two separate calls to encode the data. – Ulrich Eckhardt Jan 07 '18 at 12:17
0

You can parse your JSON using case classes and then get your event_type field from there.

case class Json(me: String, version: String, message_metadata: Message)

case class Message(event_type: String, start_date: String)

object Mapping {

  def main(args: Array[String]): Unit = {

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

    val objectMapper = new ObjectMapper() with ScalaObjectMapper
    objectMapper.registerModule(DefaultScalaModule)
    val str = "{\n  \"me\": \"a\",\n  \"version\": \"1.0\",\n  \"message_metadata\": {\n    \"event_type\": \"UpdateName\",\n    \"start_date\": \"1515\"\n  }\n}"
    val json = objectMapper.readValue(str, classOf[Json])
    //to print event_type
    println(json.message_metadata.event_type)
    //output: UpdateName

  }

}
vindev
  • 2,240
  • 2
  • 13
  • 20
0
  • You can even convert a JSON to Scala Case Class and then get the particular field from the case class.

  • Please find a working and detailed answer which I have provided using generics here.

Keshav Lodhi
  • 2,641
  • 2
  • 17
  • 23