procore-oss / blueprinter

Simple, Fast, and Declarative Serialization Library for Ruby

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Default date serialization

sihu opened this issue · comments

I created a Blueprint like that:

class FirstBlueprint < Blueprinter::Base
  identifier :id

  fields :title, :starts_at, :ends_at
end

What i found out a bit later is, that the date got printed out that way: "2022-08-05 22:38:22 +0200"

Now why is that problematic?

Firefox and Safari won't be able to parse dates in JS like that:

-> new Date('2021-11-23 11:56:20 +0100')
=> Invalid Date

-> new Date('2021-11-23T11:56:15+01:00')
=> Tue Nov 23 2021 11:56:15 GMT+0100 (Central European Standard Time)

I just see a lot of errors occurring out of that, because it's not the expected behaviour. If you do:

[0] pry(main)> { myDate: Time.zone.now }.to_json

Rails will perfectly handle that and convert it to a ISO8601. Therefore i think a blueprint should do the same?

What i asked myself? Is it not intended to use a date as a field? In the documentation i just read, that i could define a custom date format, but not, that it's needed for date fields.

Suggestion:

I would love a default configuration for dates. So that in the background it's checking by default something like field.is_a?(Date) || field.is_a?(DateTime) ? field.iso8601 : field

What do you think?

I ran into this problem myself recently. It's tricky to solve in a straightforward way. Caveat: this is a Rails project that is not using OJ or yajl-ruby.

You can use the Blueprinter.configuration.datetime_format option, but unfortunately, setting that option means Date/DateTime values will be formatted as strings if you're relying on render_to_hash anywhere, which seems incorrect. If you don't care about that, you can use just use the config option and it will format any object responding to strftime -- so both Date and DateTime will be fine.

Even more unexpected is the behavior of render vs render_as_json in a Rails project. render_as_json just calls as_json which means it uses the ActiveSupport::JSON methods, including these options:

ActiveSupport::JSON::Encoding.use_standard_json_time_format
ActiveSupport::JSON::Encoding.escape_html_entities_in_json
ActiveSupport::JSON::Encoding.time_precision
ActiveSupport::JSON::Encoding.json_encoder 

render by default calls JSON.generate which ActiveSupport::JSON takes care not to override, so the formatting will be different depending on the value of ActiveSupport::JSON::Encoding.use_standard_json_time_format:

# render_as_json
"updatedAt"=>"2021-12-20T18:04:43.311Z"

# render
\"updatedAt\":\"2021-12-20 18:04:43 UTC\"

If you just want the default Rails behavior, and you're not using a different generator like OJ, you can use this configuration:

Blueprinter.configure do |config|
  config.method = :encode
  config.generator = ActiveSupport::JSON
end

different but related issue I just discovered:

setting Blueprinter.configuration.datetime_format will format DateTime values defined as fields, but it will not transform DateTimes passed through the meta hash

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.