I was hoping that by requiring json I’ll get a working “from_json” added to my struct, just as it happened to my NamedTuples, but this code does not work:
require "json"
struct Person
property name : String
property email : String
def initialize(@name, @email)
end
end
foo = Person.new("Foo", "me@foo.bar")
p! foo
json_str = %{{"name": "Bar", "email": "bar@foobar.com"}}
bar = Person.from_json(json_str)
p! bar
The output is
Showing last frame. Use --error-trace for full trace.
In /usr/share/crystal/src/json/from_json.cr:13:3
13 | new parser
^--
Error: wrong number of arguments for 'Person.new' (given 1, expected 2)
Overloads are:
- Person.new(name, email)
Apparently the from_json will call the initialize
method with a JSON::PullParser object.
I could use that to implement parsing of the JSON, but I wonder, is this the recommended way to do it?
require "json"
struct Person
property name : String
property email : String
def initialize(@name, @email)
end
def initialize(pull)
@name = ""
@email = ""
pull.read_object do |key|
case key
when "name"
@name = pull.read_string
when "email"
@email = pull.read_string
end
end
end
end
foo = Person.new("Foo", "me@foo.bar")
p! foo
json_str = %{{"name": "Bar", "email": "bar@foobar.com"}}
bar = Person.from_json(json_str)
p! bar
You need to include JSON::Serializable in your type.
I proposed having all types be mapped to JSON/YAML automatically a long time ago: unfortunately it wasn’t well received so you have to write a bit more boilerplate.
2 Likes
Oh, I already had that with a class, but forgotten about it. Thanks. It works now.
I just hit the same issue. I tried to implement some API with NamedTuple.
But Crystal doesn’t have deep auto cast so it didn’t worked well. And also everyone advised to use record
.
I tried record
just to discover it doesn’t work with from_json
and after searching with Google why it is so I found this issue.
Would be much better if 1) Crystal had deep auto cast and 2) from_json
worked out of the box.
It deff does if you add include JSON::Serializable
.
Related: [RFC] Out of the box JSON/YAML serialization · Issue #6309 · crystal-lang/crystal · GitHub
EDIT: To be clear no one is suggesting using a class
, but record
or struct
where a record
is an easier way to make immutable structs. NamedTuples are not meant for this as others have mentioned in that reddit thread.
Yes, after finding this topic I realised that. What I meant that it would be better if it just worked out of the box.
I just had to add around 15 do; include JSON::Serializable; end
statements to my codebase. It’s a pure boilerplate, with zero meaning, reminding good old Java Enterprise time…
1 Like
I mean it’s not really a big deal. It makes it clear that that type should be JSON serializable. Maybe it’s time to revive that issue then.