Как я могу заставить PureConfig десериализовать JSON как поле JValue? - PullRequest
1 голос
/ 08 ноября 2019

Часть моей конфигурации содержит произвольный JSON. Я хочу десериализовать этот JSON как JValue для дальнейшей обработки.

Однако ConfigSource.load жалуется, что ключ type не найден.

Тестовый код:

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)
}

Вывод:

Left(ConfigReaderFailures(ConvertFailure(KeyNotFound(type,Set()),None,json),List()))

Как я могу заставить PureConfig десериализоваться в JValue?

Обновление:

Я адаптировал ответ Gagandeep к моей старой версии 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)
    }
}

Это изменило сообщение об ошибке, которое я считаю прогрессом:

Left(ConfigReaderFailures(ConvertFailure(WrongType(OBJECT,Set(STRING)),None,json),List()))

Кажется, PureConfig где-то ожидал String, но вместо этого обнаружил и Object. Я не уверен, где лежит разъединение. Я использую cur.asString, чтобы гарантировать, что элемент возвращается как соответствующий тип.

Обновление 2:

Это, вероятно, не самое надежное решение, ноэто работает для моего теста:

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))
      )
    )
  }
}

1 Ответ

2 голосов
/ 08 ноября 2019

JValue не является классом, кортежем, классом дела или запечатанной чертой, поэтому макрос не может производить для него автоматическую деривацию. Определение читателя для него должно помочь.

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)
}
...