JSON::Serializable on optional array becomes nil. Why not []. Impossible to tier on nil


I’m new to this pleasent crystal. And also unfamiliary with usage on most bells and whistles here, but…

I got stuck when parsing JSON.

There are optional fields in the input. No problems with basic types.

But optional on Array becomes Nil if not present. I would like to get an empty array instead.


class ARecursive
    include JSON::Serializable
    property kind : String
    property someopt : String?
    property deeper : Array(ARecursive)?

I parse the input like

thejson = ARecursive.from_json(File.read(somefilename))

But I can’t iter on this as deeper is declared as

(Array(ARecursive) | Nil) by JSON::Serializable

This iteration will not compile

thejson.deeper.each {|d|d}
Error: undefined method 'each' for Nil (compile-time type is (Array(ARecursive) | Nil))

What to do? Is it possible to iter on such a type using some smart pattern? Or are there any other set up on JSON::Serializable?

The recursive is not the problem. (I think?)


The simplist way to fix this is just give that property a default value. E.g.

property deeper : Array(ARecursive) = [] of ARecursive

Then if it’s not supplied in the JSON, it’ll use that, otherwise what’s in the JSON.


Thank’s a lot. The power of you and crystal shows up.


1 Like

Alternatively, you could also accept the Nil type and add a guard for that when you want to iterate:

if deeper = thejson.deeper
  deeper.each {|d|d}
# or (shorter):
thejson.deeper.try &.each {|d|d}

I will try that too; for learning at least.

Thank you for your friendly support