Sample JSON read from file:
{
"category": "[{\"a\":3,\"b\":11,\"c\":86}]",
"ids": "[\"1234\", \"5678\"]",
"uid": "55555",
"flag": true
}
Current Code:
val filePath = args(0)
val jsonFileString = Source.fromFile(filePath).getLines.mkString.stripMargin
val mapper = new ObjectMapper().registerModules(DefaultScalaModule)
val jsonStringObj = mapper.readTree(jsonFileString)
val ids = jsonStringObj.get("ids").asText()
This works fine to get me the ids
when the json file contains it, but I want to provide a default value in case the key "ids" is not present in the JSON file. How do I do that?
In python I could do something like json_dict.get('ids', 'default_value')
. I am looking for an equivalent.
You have to cover 4 cases:
null
Many ways of solving this:
ObjectMapper
you created and trying to follow some scala styleval ids = Option(jsonString.get("ids")) // JsonNode.get return null if the field is not present
.filterNot(_.isNull) // if the filter is present but the value is null it returns a JsonNodeType.NULL
.map(_.asText()) // transform to text
.getOrElse("default-value") // if the Option is None we get a default value
if
sval idsNode = mapper
.readTree(jsonFileString)
.get("ids") // this returns null if field is not present
val ids =
if(idsNode == null || idsNode.isNull) // if field is not present or it's present but value is null
"default value" // if true get default value
else idsNode.asText() // if false get the value of the field
get
we use path
from javadoc of path
method
This method is similar to
get(String)
, except that instead of returningnull
if no such value exists (due to this node not being an object, or object not having value for the specified field), a "missing node" (node that returns true forisMissingNode
) will be returned. This allows for convenient and safe chained access via path calls.
val idsNode = mapper
.readTree(jsonFileString)
.path("ids") // this returns `MissingNode` if field is not present
val ids =
if(idsNode.isNull || idsNode.isMissingNode) // check if the node is null or missing
"default value" // defualt value
else idsNode.asText() // value from the json
case class
ignoring unknown fields (a bit more scala style)// define a case class outside the block of the JsonMapper
case class IdsWrapper(ids: Option[String])
val mapper = JsonMapper
.builder()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.addModule(DefaultScalaModule)
.build()
val idsNode = mapper
.readValue[IdsWrapper](jsonFileString)
.ids
.getOrElse("default value")
jackson is a java library to serialize/deserialize json. jackson-module-scala is an extension of that library. It's not exactly the most popular library in the scala ecosystem. So, if you are not restricted to that library, I would suggest to consider other ones such as the ones listed below:
val ids = ujson.read(jsonFileString)("ids")
.strOpt
.getOrElse("default value")
val ids = (Json.parse(jsonFileString) \ "ids")
.asOpt[String]
.getOrElse("default value")