jsoniter-scala icon indicating copy to clipboard operation
jsoniter-scala copied to clipboard

There is no fallback setting for arrays in the case of [], null

Open 2MD opened this issue 4 years ago • 2 comments

We have JsonCodecMaker.makeWithRequiredCollectionFields But if input: { "arr": null } and case class Test(arr: Seq[Int])

We will be have arr = Seq() empty collection. But sometimes we need Exception in this case. Wiil be good if we have some setting for macros.

Likewise in case for input: { "arr": [] } and case class Test(arr: Seq[Int])

2MD avatar May 31 '21 13:05 2MD

The best option is making the check of non-emptiness by the collection type itself.

As an example, you can define case class Test(arr: ::[Int]) and got the non-emptiness check for free.

Currently to solve your issue for Seq[Int] the following custom codec can be used:

implicit val nonEmptySeqCodec: JsonValueCodec[Seq[Int]] = new JsonValueCodec[Seq[Int]] {
  override def decodeValue(in: JsonReader, default: Seq[Int]): Seq[Int] =
    if (in.isNextToken('[')) {
      if (in.isNextToken(']')) {
        if (default ne null) default
        else in.decodeError("expected non-empty JSON array")
      } else {
        in.rollbackToken()
        val x = Seq.newBuilder[Int]
        while ({
          x.addOne(in.readInt())
          in.isNextToken(',')
        }) ()
        if (in.isCurrentToken(']')) x.result()
        else in.arrayEndOrCommaError()
      }
    } else {
      if (default ne null) in.readNullOrTokenError(default, '[')
      else in.decodeError("expected non-empty JSON array")
    }

  override def encodeValue(x: Seq[Int], out: JsonWriter): Unit = {
    if (x.isEmpty) out.encodeError("expected non-empty sequence")
    out.writeArrayStart()
    x.foreach(out.writeVal)
    out.writeArrayEnd()
  }

  override def nullValue: Seq[Int] = null
}

plokhotnyuk avatar May 31 '21 14:05 plokhotnyuk

Thank you!

2MD avatar May 31 '21 14:05 2MD