1

I want to create an endpoint that receives JSON data and should parse it as an array of strings.

POST /
{
  "keys": ["foo", "bar"]
}

I'm running into problems with the type system. This is what I tried (.as(Array(String))) but it does not compile:

require "kemal"

def print_keys(keys : Array(String))
  puts "Got keys: #{keys}"
end

post "/" do |env|
  keys = env.params.json["keys"].as(Array(String)) # <-- ERROR
  print_keys(keys)
end

Kemal.run

The error message is:

 8 | keys = env.params.json["keys"].as(Array(String)) # <-- ERROR
        ^
Error: can't cast (Array(JSON::Any) | Bool | Float64 | Hash(String, JSON::Any) | Int64 | String | Nil) to Array(String)

If I change the code to parse not Array(String) but instead String, it compiles without problems. Why does it make a difference in the .as method that the type is Array(String) instead of String?

How can the code be changed to parse arrays of strings?

Philipp Claßen
  • 41,306
  • 31
  • 146
  • 239

1 Answers1

1

I found an example in the documentation, which uses JSON.mapping. In my concrete example, it could be written as follows:

require "kemal"

def print_keys(keys : Array(String))
  puts "Got keys: #{keys}"
end

class KeyMappings
  JSON.mapping({
    keys: Array(String)
  })
end

post "/" do |env|
  json = KeyMappings.from_json env.request.body.not_nil!
  print_keys(json.keys)
end

Kemal.run
Philipp Claßen
  • 41,306
  • 31
  • 146
  • 239