learncodes123
learncodes123

Reputation: 401

Array of objects in Crystal

Beginner question:

How to make an Array of objects from a Struct in Crystal? Or how to make an array of objects in Crystal? I am trying to emulate the go code.

struct Book 
   def initialize(
     @Id : Int32,
     @Title : String,
     @Author : String, 
     @Desc : String
   )
   end
 end

 books = [] of Int32 | String <--- This is wrong
 book1 = Book.new(1, "Hello", "Me", "This is a test.")


GO CODE: 

type Book struct {
   Id     int    `json:"id"`
   Title  string `json:"title"`
   Author string `json:"author"`
   Desc   string `json:"desc"`
}

var Books = []models.Book{
   {
       Id:     1,
       Title:  "Golang",
       Author: "Gopher",
       Desc:   "A book for Go",
   },
}

Changing to a class allows me to return a new object. Which I am sure is the wrong way to make a new object in Crystal? I can then add objects to the array.

  class Book 
    def initialize(id : Int32, title : String, author : String, desc : String)
      @id = id
      @title = title
      @author = author
      @desc = desc
    end

    def object 
      {
        @id,
        @title,
        @author,
        @desc
    }
    end 

  end


  books = [] of Book <--- HOW TO SET ARRAY OF OBJECTS ON THE TYPE?
  book1 = Book.new(1, "Hello", "Me", "This is a test.")
  puts book1.object
  books << book1.object
  puts books

Upvotes: 1

Views: 375

Answers (2)

learncodes123
learncodes123

Reputation: 401

It seems really what I wanted, and what was not the same as the struct version in go was an Array of Hashes, which in turn is an Array of Objects, as everything is an Object in Crystal?*.

  hash = [] of Hash(Int32, String) # Array of Hashes
  hash0 = {0 => "Jackson0"}
  hash1 = {1 => "Jackson1"}
  hash2 = {2 => "Jackson2"}
  hash3 = {3 => "Jackson3"}

  #Append the hashes to the array

  hash << hash0
  hash << hash1
  hash << hash2
  hash << hash3

OR

  (0..3).each do |i| 
    hash << {i => "Jackson#{i}"}
  end
  RESULT : [{0 => "Jackson0"}, {1 => "Jackson1"}, {2 => "Jackson2"}, {3 => "Jackson3"}]

  # Display them as JSON

  get "/" do
    hash.to_json
  end

RESULT : [{"0":"Jackson0"},{"1":"Jackson1"},{"2":"Jackson2"},{"3":"Jackson3"}]

Which in turn can be queried using hash[0][1] 

RESULT : {"1": "Jackson1"}

Upvotes: 1

Amadan
Amadan

Reputation: 198314

You can write

books = [] of Book
books << book1

or you can simply do this, and let Crystal recognise the type:

books = [book1]

The closest to the original is

books = [
  Book.new(1, "Hello", "Me", "This is a test.")
]

EDIT: If you need JSON, you need to implement it, as described in the documentation. The easiest is to include JSON::Serializable:

require "json"

module TestBookJSON

  struct Book
    include JSON::Serializable      # <-- this

    def initialize(
      @Id : Int32,
      @Title : String,
      @Author : String,
      @Desc : String
    )
    end
  end

  books = [] of Book
  book1 = Book.new(1, "Hello", "Me", "This is a test.")
  books << book1
  puts books.to_json
  # => [{"Id":1,"Title":"Hello","Author":"Me","Desc":"This is a test."}]

end

Upvotes: 1

Related Questions