2

I want to read in a json object into a scala class that keeps part of the json object as a string without trying to parse it.

This is what the json looks like:

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

I am using the jackson library. This is my mapper:

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

This is my class:

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

, which is how I want my resulting object to look.

This is the code parsing it:

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

Error message I'm getting: Can not deserialize instance of java.lang.String out of START_OBJECT token when it starts parsing the contractDefinition

2
  • What json library are you using? Commented Oct 25, 2019 at 19:45
  • Jackson. I added more details to the question. Commented Oct 25, 2019 at 20:02

1 Answer 1

2

If you are allowed to use other libraries and type of the contractDefinition field is not restricted to String then try jsoniter-scala's feature of extraction raw JSON values to byte arrays.

You will need to add dependencies:

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
)

Then define types with codecs and parse the input:

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)

Printed result will be:

List(ContractJson(NullContract, {
  "column": "age",
  "conditions": [
    {
      "conditionType": "equalsCondition",
      "conditionDefinition": {
        "column": "species",
        "value": "person"
      }
    }
  ]
}))
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.