Skip to content

Instantly share code, notes, and snippets.

@malclocke
Last active August 14, 2017 04:42
Show Gist options
  • Save malclocke/82e6c8712b5be0c1163924f6d8edca71 to your computer and use it in GitHub Desktop.
Save malclocke/82e6c8712b5be0c1163924f6d8edca71 to your computer and use it in GitHub Desktop.
#
# Example of how to convert CSV data on read, in this case parsing
# some JSON in a CSV.
#
require 'csv'
require 'json'
csv = <<EOT
id,json_stuff
1,"{""foo"":""bar""}"
EOT
CSV.parse(csv, headers: true) do |row|
puts row["json_stuff"].class # => String
end
# You can create a lambda that takes one or two arguments to convert values
# on read.
#
# field is the raw value, field_info is a CSV::FieldInfo struct with the
# members index, line and header
json_parser_converter = lambda do |field, field_info|
# Every single field in the CSV gets passed to this block, so you need to
# the field content or catch exceptions if the field data can't be converted.
if field_info.header == "json_stuff" && field != ""
JSON.parse(field)
else
field
end
end
CSV.parse(csv, headers: true, converters: [json_parser_converter]) do |row|
puts row["json_stuff"].class # => Hash
end
# The CSV lib also has an internal global hash of converters
CSV::Converters[:json_parser_converter] = json_parser_converter
# Note the converter is specified as a symbol here.
CSV.parse(csv, headers: true, converters: [:json_parser_converter]) do |row|
puts row["json_stuff"].class # => Hash
end
# You can use :all to use all converters, but it will only use all the built in
# converters, not any custom ones you have added.
CSV.parse(csv, headers: true, converters: [:all]) do |row|
puts row["json_stuff"].class # => String
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment