Как прочитать часть вложенного объекта json в виде строки в Scala - PullRequest
1 голос
/ 25 октября 2019

Я хочу прочитать объект json в класс scala, который хранит часть объекта json в виде строки, не пытаясь ее проанализировать.

Вот как выглядит json:

[
  {
    "contractType": "NullContract",
    "contractDefinition": {
      "column": "age",
      "conditions": [
        {
          "conditionType": "equalsCondition",
          "conditionDefinition": {
            "column": "species",
            "value": "person"
          }
        }
      ]
    }
  }
]

Я использую библиотеку Джексона. Это мой картограф:

val mapper = new ObjectMapper()
    .registerModule(DefaultScalaModule)
    .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
    .setSerializationInclusion(Include.NON_ABSENT)

Это мой класс:

case class ContractJson(contractType: String, contractDefinition: String)

, так я хочу, чтобы мой результирующий объект выглядел.

Это кодпарсинг:

val contractJson: Array[ContractJson] = mapper.readValue(contractsJsonString, classOf[Array[ContractJson]])

Я получаю сообщение об ошибке: Can not deserialize instance of java.lang.String out of START_OBJECT token когда начинается анализ contractDefinition

1 Ответ

0 голосов
/ 25 октября 2019

Если вам разрешено использовать другие библиотеки, и тип поля contractDefinition не ограничен String, тогда попробуйте функцию * jsoniter-scala для извлечения необработанных значений JSON в байтовые массивы.

Вам нужно будет добавить зависимости:

libraryDependencies ++= Seq(
  "com.github.plokhotnyuk.jsoniter-scala" %% "jsoniter-scala-core"   % "1.1.0" % Compile,
  "com.github.plokhotnyuk.jsoniter-scala" %% "jsoniter-scala-macros" % "1.1.0" % Provided // required only in compile-time
)

Затем определить типы с помощью кодеков и проанализировать ввод:

import java.nio.charset.StandardCharsets.UTF_8

import com.github.plokhotnyuk.jsoniter_scala.macros._
import com.github.plokhotnyuk.jsoniter_scala.core._

import scala.util.hashing.MurmurHash3

object RawVal {
  def apply(s: String) = new RawVal(s.getBytes)

  implicit val codec: JsonValueCodec[RawVal] = new JsonValueCodec[RawVal] {
    override def decodeValue(in: JsonReader, default: RawVal): RawVal = new RawVal(in.readRawValAsBytes())

    override def encodeValue(x: RawVal, out: JsonWriter): Unit = out.writeRawVal(x.bs)

    override val nullValue: RawVal = new RawVal(new Array[Byte](0))
  }
}

case class RawVal private(bs: Array[Byte]) {
  def this(s: String) = this(s.getBytes(UTF_8))

  override lazy val hashCode: Int = MurmurHash3.arrayHash(bs)

  override def equals(obj: Any): Boolean = obj match {
    case that: RawVal => java.util.Arrays.equals(bs, that.bs)
    case _ => false
  }

  override def toString: String = new String(bs, UTF_8)
}

case class ContractJson(contractType: String, contractDefinition: RawVal)

implicit val codec: JsonValueCodec[List[ContractJson]] = JsonCodecMaker.make(CodecMakerConfig)

val jsonBytes =
  """[
    |  {
    |    "contractType": "NullContract",
    |    "contractDefinition": {
    |      "column": "age",
    |      "conditions": [
    |        {
    |          "conditionType": "equalsCondition",
    |          "conditionDefinition": {
    |            "column": "species",
    |            "value": "person"
    |          }
    |        }
    |      ]
    |    }
    |  }
    |]
    |""".stripMargin.getBytes("UTF-8")

val contractJsons = readFromArray(jsonBytes)

println(contractJsons)

Печатным результатом будет:

List(ContractJson(NullContract, {
  "column": "age",
  "conditions": [
    {
      "conditionType": "equalsCondition",
      "conditionDefinition": {
        "column": "species",
        "value": "person"
      }
    }
  ]
}))
...