twharmon
twharmon

Reputation: 4272

.to_json on Array() not working in Crystal

I have a class:

class User
    property id : Int32?
    property email : String?
    property password : String?

    def to_json : String
        JSON.build do |json|
            json.object do
                json.field "id", self.id
                json.field "email", self.email
                json.field "password", self.password
            end
        end
    end

    # other stuff
end

This works great with any user.to_json. But when I have Array(User) (users.to_json) it throws this error at compile time:

in /usr/local/Cellar/crystal-lang/0.23.1_3/src/json/to_json.cr:66: no overload matches 'User#to_json' with type JSON::Builder Overloads are: - User#to_json() - Object#to_json(io : IO) - Object#to_json()

  each &.to_json(json)

Array(String)#to_json works fine, so why doesn't Array(User)#to_json?

Upvotes: 3

Views: 527

Answers (1)

Vitalii Elenhaupt
Vitalii Elenhaupt

Reputation: 7326

Array(User)#to_json doesn't work because User needs to have to_json(json : JSON::Builder) method (not to_json), just like String has:

require "json"

class User
  property id : Int32?
  property email : String?
  property password : String?

  def to_json(json : JSON::Builder)
    json.object do
      json.field "id", self.id
      json.field "email", self.email
      json.field "password", self.password
    end
  end
end

u = User.new.tap do |u|
  u.id = 1
  u.email = "[email protected]"
  u.password = "****"
end

u.to_json      #=> {"id":1,"email":"[email protected]","password":"****"}
[u, u].to_json #=> [{"id":1,"email":"[email protected]","password":"****"},{"id":1,"email":"[email protected]","password":"****"}]

Upvotes: 7

Related Questions