Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert Json to a Map[String, String]

Tags:

json

scala

circe

I have input json like

{"a": "x", "b": "y", "c": "z", .... }

I want to convert this json to a Map like Map[String, String]

so basically a map of key value pairs.

How can I do this using circe?

Note that I don't know what keys "a", "b", "c" will be present in Json. All I know is that they will always be strings and never any other data type.

I looked at Custom Decoders here https://circe.github.io/circe/codecs/custom-codecs.html but they work only when you know the tag names.

I found an example to do this in Jackson. but not in circe

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

val data = """
    {"a": "x", "b", "y", "c": "z"}
"""
val mapper = new ObjectMapper
mapper.registerModule(DefaultScalaModule)
mapper.readValue(data, classOf[Map[String, String]])
like image 705
Knows Not Much Avatar asked Dec 17 '22 19:12

Knows Not Much


1 Answers

While the solutions in the other answer work, they're much more verbose than necessary. Off-the-shelf circe provides an implicit Decoder[Map[String, String]] instance, so you can just write the following:

scala> val doc = """{"a": "x", "b": "y", "c": "z"}"""
doc: String = {"a": "x", "b": "y", "c": "z"}

scala> io.circe.parser.decode[Map[String, String]](doc)
res0: Either[io.circe.Error,Map[String,String]] = Right(Map(a -> x, b -> y, c -> z))

The Decoder[Map[String, String]] instance is defined in the Decoder companion object, so it's always available—you don't need any imports, other modules, etc. Circe provides instances like this for most standard library types with reasonable instances. If you want to decode a JSON array into a List[String], for example, you don't need to build your own Decoder[List[String]]—you can just use the one in implicit scope that comes from the Decoder companion object.

This isn't just a less verbose way to solve this problem, it's the recommended way to solve it. Manually constructing an explicit decoder instance and converting from Either to Try to compose parsing and decoding operations is both unnecessary and error-prone (if you do need to end up with Try or Option or whatever, it's almost certainly best to do that at the end).

like image 126
Travis Brown Avatar answered Jan 08 '23 03:01

Travis Brown