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, &block) ⇒ 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



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
67
# File 'lib/json_csv/json_to_csv.rb', line 31

def create_csv_for_json_records(csv_outfile_path, header_sort_comparator = DEFAULT_HEADER_SORT_COMPARATOR, &block)
  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', &block)

    # 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



21
22
23
# File 'lib/json_csv/json_to_csv.rb', line 21

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.



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

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



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

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)


106
107
108
109
110
# File 'lib/json_csv/json_to_csv.rb', line 106

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

  false
end