Part of my config contains arbitrary JSON. I want to deserialize that JSON as a JValue for later processing.
However, ConfigSource.load
complains that the type
key is not found.
Test code:
import org.json4s.JsonAST.JValue
import pureconfig.ConfigReader.Result
import pureconfig._
import pureconfig.generic.auto._
object PureConfig2JValue extends App {
case class Config(json: JValue)
val source: ConfigObjectSource = ConfigSource.string("{ \"json\": { \"test\": \"test\" } }")
val loadedSource: Result[Config] = source.load[Config]
println(loadedSource)
}
Output:
Left(ConfigReaderFailures(ConvertFailure(KeyNotFound(type,Set()),None,json),List()))
How can I get PureConfig to deserialize to a JValue?
Update:
I adapted Gagandeep's answer to my older version of PureConfig:
implicit val configReader: ConfigReader[JValue] = new ConfigReader[JValue] {
override def from(cur: ConfigCursor): Either[ConfigReaderFailures, JValue] =
cur.asString match {
case Right(jsonString: String) => Right(parse(jsonString))
case Left(configReaderFailures: ConfigReaderFailures) => Left(configReaderFailures)
}
}
It changed the error message, which I take to be progress:
Left(ConfigReaderFailures(ConvertFailure(WrongType(OBJECT,Set(STRING)),None,json),List()))
It seems PureConfig expected a String somewhere but instead found and Object. I'm not sure where the disconnect lies. I'm using cur.asString
to ensure the item is returned as its appropriate type.
Update 2:
This probably isn't the most robust solution, but it works for my test case:
implicit val configReader: ConfigReader[JValue] = new ConfigReader[JValue] {
override def from(cur: ConfigCursor): Either[ConfigReaderFailures, JValue] = {
Right(
// Parse PureConfig-rendered JSON.
parse(
// Render config as JSON.
cur.value.render(ConfigRenderOptions.concise.setJson(true))
)
)
}
}
JValue is not a class, tuple, case class or a sealed trait, hence macro cannot produce automatic derivation for it. Defining a reader for it should help.
import org.json4s._
import org.json4s.native.JsonMethods._
implicit val configReader = new ConfigReader[JValue] {
override def from(cur: ConfigCursor): Result[JValue] = cur.asString.map(parse)
}