Find a better way to convert json any to hash(string,string)

my version

headers = task["headers"]?
.try &.as_h?
.try &.to_h { |k, v| {k, v.as_s} } 
|| {} of String => String

I’d recommend having a read of if-var control flow from the docs, but to solve this you’d likely want to handle the nilable case earlier:

headers = task["headers"]?.try(&.as_h) || {} of String => JSON::Any
headers = headers.transform_values &.as_s

EDIT: typing & method fixes

1 Like

Do you have a way to avoid receiving it as a JSON::Any to begin with?

struct Task
  include JSON::Serializable

  getter headers : Hash(String, String)
  # ...
end

task = Task.from_json(json)

Then task.headers will just be a Hash(String, String) and you won’t have to perform the conversion after it’s been parsed.

2 Likes

I know this but I don’t really like using it.

1 Like

Based on my experience in other languages, Any is usually lazy parsed, but I don’t know if Crystal is also …

I would be thoroughly interested in understanding this perspective. Any time I reach for JSON::Any it makes me want to swap it out in favor of JSON::Serializable objects.

That depends on how you define “lazily”. It’s lazy in that you can parse from an IO so that you don’t need to hold the entire JSON-serialized representation in memory before starting parsing, but it’s not the form of laziness where, for example, it won’t start parsing until you retrieve an object’s key. What is the importance of laziness here?