Module: JsonCsv::JsonToCsv::ClassMethods

Defined in:
lib/json_csv/json_to_csv.rb

Constant Summary collapse

DEFAULT_HEADER_SORT_COMPARATOR =
lambda do |header1, header2|
  # Ensure correct alphabetical sorting AND numeric sorting via zero-padding of numbers
  header1_with_zero_padding = header1.gsub(/(?<=\[)\d+(?=\])/) { |capture| capture.to_i.to_s.rjust(5, '0') }
  header2_with_zero_padding = header2.gsub(/(?<=\[)\d+(?=\])/) { |capture| capture.to_i.to_s.rjust(5, '0') }
  header1_with_zero_padding <=> header2_with_zero_padding
end

Instance Method Summary collapse

Instance Method Details

#create_csv_for_json_records(csv_outfile_path, header_sort_comparator = DEFAULT_HEADER_SORT_COMPARATOR) ⇒ Object

Example usage: create_csv_for_json_records(‘/path/to/file.csv’) do |csv_builder|

json_docs.each do |json_doc|
  csv_builder.add(json_hash)
end

end



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/json_csv/json_to_csv.rb', line 29

def create_csv_for_json_records(csv_outfile_path, header_sort_comparator = DEFAULT_HEADER_SORT_COMPARATOR)
  csv_temp_outfile_path = csv_outfile_path + '.temp'

  begin
    # Step 1: Build CSV with unsorted headers in temp file
    csv_headers = JsonCsv::CsvBuilder.create_csv_without_headers(csv_temp_outfile_path, 'wb') do |csv_builder|
      yield csv_builder
    end

    # Step 2: Sort CSV columns by header, based on column_header_comparator
    original_to_sorted_index_map = JsonCsv::CsvBuilder.original_header_indexes_to_sorted_indexes(csv_headers, header_sort_comparator)
    CSV.open(csv_outfile_path, 'wb') do |final_csv|
      # Open temporary CSV for reading
      CSV.open(csv_temp_outfile_path, 'rb') do |temp_csv|

        # write out ordered header row
        reordered_header_row = []
        csv_headers.each_with_index do |header, index|
          reordered_header_row[original_to_sorted_index_map[index]] = header
        end

        final_csv << reordered_header_row

        temp_csv.each do |temp_csv_row|
          reordered_temp_csv_row = []
          # write out ordered data row
          temp_csv_row.each_with_index do |cell_value, index|
            reordered_temp_csv_row[original_to_sorted_index_map[index]] = cell_value
          end
          final_csv << reordered_temp_csv_row
        end
      end
    end
  ensure
    # Always delete the temporary CSV
    FileUtils.rm_f(csv_temp_outfile_path)
  end
end

#default_header_comparison(header1, header2) ⇒ Object



19
20
21
# File 'lib/json_csv/json_to_csv.rb', line 19

def default_header_comparison(header1, header2)
  DEFAULT_HEADER_SORT_COMPARATOR.call(header1, header2)
end

#flatten_hash(obj, parent_path = '', flat_hash_to_build = {}) ⇒ Object

This method calls itself recursively while flattening a hash, and during this sequence of calls the obj param may either be a hash or an array.



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/json_csv/json_to_csv.rb', line 81

def flatten_hash(obj, parent_path = '', flat_hash_to_build = {})
  if obj.is_a?(Hash)
    obj.each do |key, val|
      if key_contains_unallowed_characters?(key)
        raise ArgumentError, 'Cannot deal with hash keys that contain "[" or "]" or "." because these characters have special meanings in CSV headers.'
      end
      path = parent_path + (parent_path.empty? ? '' : '.') + key
      flatten_hash(val, path, flat_hash_to_build)
    end
  elsif obj.is_a?(Array)
    obj.each_with_index do |el, index|
      path = parent_path + "[#{index}]"
      flatten_hash(el, path, flat_hash_to_build)
    end
  else
    flat_hash_to_build[parent_path] = obj unless obj.nil? || obj == '' # ignore nil or empty string values
  end

  flat_hash_to_build
end

#json_hash_to_flat_csv_row_hash(json_hash) ⇒ Object

Converts the given json_hash into a flat csv hash, converting all values to strings (because CSVs are dumb and don’t store info about data types) Set first_index to 1 if you want the first element in an array to



72
73
74
75
76
77
# File 'lib/json_csv/json_to_csv.rb', line 72

def json_hash_to_flat_csv_row_hash(json_hash)
  flat = flatten_hash(json_hash)
  # Convert values to strings because in the CSV file, all values are strings
  flat.each { |key, val| flat[key] = val.nil? ? '' : val.to_s }
  flat
end

#key_contains_unallowed_characters?(key) ⇒ Boolean

Returns:

  • (Boolean)


102
103
104
105
# File 'lib/json_csv/json_to_csv.rb', line 102

def key_contains_unallowed_characters?(key)
  return true if key.index('[') || key.index(']') || key.index('.')
  false
end