Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 14 additions & 27 deletions core/src/main/scala/caliban/interop/jsoniter/jsoniter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ private[caliban] object ValueJsoniter {
StringValue(in.readString(null))
case x if x == '-' || (x >= '0' && x <= '9') =>
in.rollbackToken()
numberParser(in)
parseNumber(in)
case 'n' =>
in.readNullOrError(NullValue, "unexpected JSON value")
case 'f' | 't' =>
Expand Down Expand Up @@ -169,7 +169,7 @@ private[caliban] object ValueJsoniter {
StringValue(in.readString(null))
case x if x == '-' || (x >= '0' && x <= '9') =>
in.rollbackToken()
numberParser(in)
parseNumber(in)
case 'n' =>
in.readNullOrError(NullValue, "unexpected JSON value")
case 'f' | 't' =>
Expand Down Expand Up @@ -203,32 +203,19 @@ private[caliban] object ValueJsoniter {
in.decodeError(s"unexpected token $c")
}

private val numberParser: JsonReader => Value = in => {
in.setMark()
var digits = 0
var b = in.nextByte()
if (b == '-') b = in.nextByte()
try
while (b >= '0' && b <= '9') {
digits += 1
b = in.nextByte()
}
catch {
case _: JsonReaderException => // ignore the end of input error for now
private def parseNumber(in: JsonReader): Value =
in.readNumber(null) match {
case l: java.lang.Long =>
val asLong = l.longValue()
val asInt = asLong.toInt
// Check if the number can fit in an Int (most common case)
if (asInt.toLong == asLong) Value.IntValue.IntNumber(asInt)
else Value.IntValue.LongNumber(asLong)
case bd: java.math.BigDecimal =>
Value.FloatValue.BigDecimalNumber(bd)
case bi: java.math.BigInteger =>
Value.IntValue.BigIntNumber(bi)
Comment on lines +208 to +217

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@plokhotnyuk I'm guessing that you're not planning on returning any other instances of java.lang.Number in the future, is that right?

If that's the case, it might be worth to document this in the scaladoc of readNumber. Or if you're planning on returning any different types, let me know so I can add a default case

}
in.rollbackToMark()

if ((b | 0x20) != 'e' && b != '.') {
if (digits < 19) {
if (digits < 10) Value.IntValue.IntNumber(in.readInt())
else Value.IntValue.LongNumber(in.readLong())
} else {
val x = in.readBigInt(null)
if (x.bitLength < 64) Value.IntValue.LongNumber(x.longValue)
else Value.IntValue.BigIntNumber(x.bigInteger)
}
} else Value.FloatValue.BigDecimalNumber(in.readBigDecimal(null).bigDecimal)
}

val inputValueCodec: JsonValueCodec[InputValue] = new JsonValueCodec[InputValue] {
override def decodeValue(in: JsonReader, default: InputValue): InputValue =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,22 @@ object GraphQLRequestJsoniterSpec extends ZIOSpecDefault {
suite("GraphQLRequestJsoniterSpec")(
test("can be parsed from JSON by jsoniter") {
val request =
"""{"query": "{}", "operationName": "op", "variables": {"hello":"world","answer":42,"isAwesome":true, "name": null}}"""
"""{"query": "{}", "operationName": "op", "variables": {"hello":"world","intValue":42,"longValue":99999999999,"bigIntValue":9223372036854775810,"decimalValue":1.1,"bigDecimalValue":4.4028235E38,"isAwesome":true, "name": null}}"""
assert(readFromString[GraphQLRequest](request))(
equalTo(
GraphQLRequest(
query = Some("{}"),
operationName = Some("op"),
variables = Some(
Map(
"hello" -> Value.StringValue("world"),
"answer" -> Value.IntValue(42),
"isAwesome" -> Value.BooleanValue(true),
"name" -> Value.NullValue
"hello" -> Value.StringValue("world"),
"intValue" -> Value.IntValue.IntNumber(42),
"longValue" -> Value.IntValue.LongNumber(99999999999L),
"bigIntValue" -> Value.IntValue.BigIntNumber(BigInt("9223372036854775810")),
"decimalValue" -> Value.FloatValue(BigDecimal("1.1")),
"bigDecimalValue" -> Value.FloatValue(BigDecimal("4.4028235E38")),
"isAwesome" -> Value.BooleanValue(true),
"name" -> Value.NullValue
)
)
)
Expand Down