Int in json needs to be less than Int64?

I have a case there I have a 127 bit int in a json file.

I get the following error:

Unhandled exception: Invalid Int64: "186709961001538790100634132976990" at line 94, column 19 (JSON::ParseException)

Is there some way to get json to have int128?

If you are also generating the JSON (or at least specifying its schema), then you could represent the value as a string and convert it using String#to_i128 (exactly how depends on how you’re parsing the JSON). If you don’t have any control over the JSON, I’m not sure what you can do.

I am not generating the json, so is there no way to parse a generator with i128?

Pretty sure 128 bit integer support is still a fairly new. So possible the JSON and YAML modules just need to be updated to support them. For now, I’d do something like what @RespiteSage suggested and deserialize it as a string and then manually cast it to an Int128. String::RawConverter - Crystal 1.8.0-dev May be useful for this use case.

I’d also prob open an issue about it. Somewhat relates to Unhandled exception: Invalid Int64 · Issue #11490 · crystal-lang/crystal · GitHub.

1 Like

I opened up an issue, it is just that having the int as a string, could be very problematic for what my use case is, since it also deals with a lot of strings and numbers in general. And also it is a bit hard to cast a value inside of a json if you can’t parse it.

Are you using JSON.parse or JSON::Serializable?

If you’re using JSON::Serializable, you can make a custom converter:

require "json"

json = %([{"value": 1},{"value": 186709961001538790100634132976990}])

class ToInt128Converter
  def self.from_json(parser : JSON::PullParser) : Int128
    value = parser.read_raw
    value.to_i128
  end
  
  def self.to_json(value : Int128, builder : JSON::Builder) : Nil
    builder.number value
  end
end

class ValueHaver
  include JSON::Serializable
  
  @[JSON::Field(converter: ToInt128Converter)]
  getter value : Int128
  
  def initialize(@value)
  end
end

a = Array(ValueHaver).from_json json

puts a.map &.value # => [1, 186709961001538790100634132976990]

That said, this is the first custom JSON converter I’ve written, so use this code at your own risk.

4 Likes

Oh, looks like we’re missing Int128.from_json (for JSON::Serizalizable) as well as 128-bit (and possibly larger) integers for JSON::Any.

1 Like

Yeah, I changed from i64 to i128 in some places and compiled the language and that made so I could parse json.

What to note is that this could be causing a lot of bugs. One of my dependencies I use didn’t work after this change.

In lib/liquid/src/liquid/any.cr:5:5

 5 | @raw = raw.to_i64
     ^---
Error: instance variable '@raw' of JSON::Any must be (Array(JSON::Any) | Bool | Float64 | Hash(String, JSON::Any) | Int128 | String | Nil), not Int64