json_csv 0.0.5 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f70535d234603ac01375388383a3823da0f73673
4
- data.tar.gz: cdae7c0ddfa419662a18a097a7373e8d196a1f48
3
+ metadata.gz: cca6d71ea7947967ea15bfa7fd89195549e1f5b4
4
+ data.tar.gz: dca198bcf9db549b57a9c09bac5661194658b12e
5
5
  SHA512:
6
- metadata.gz: 8793368170c8003b8bea3af8b6e84e410973589458c8ac0d244702bed2d779ee914c24c028929053ef10e4cc4ce3d8cc054324700a453d3858a95401df4d402c
7
- data.tar.gz: 871e4bfcfb63b869b60f9bc413c32823f118f2bfaec4296032ea7b7bffa07876ff0db5e66cf782b2c9d76800a0fd81e8b38fd046120ee782f18390657c20fd69
6
+ metadata.gz: 8929b7911dbb7da2e29a56c8e6a2b93df9ab203d3202d435b3932c782654f7392b3dce1d27215021b53544864a8569a6e5b230a0bd029a21745dc27ace2e2989
7
+ data.tar.gz: c00fed1d0fbed0b41c0261005909290ea48990cf7b4532bc0ff60f16cbaa1251c3aaa5244f6cad0cf695d66e43f822abf9f92a881632da1acdf49143b8e37d8a
@@ -0,0 +1,23 @@
1
+ module JsonCsv
2
+ module ArrayNotation
3
+ BRACKETS = 'BRACKETS'.freeze
4
+ DASH = 'DASH'.freeze
5
+
6
+ VALID_ARRAY_NOTATIONS = [BRACKETS, DASH].freeze
7
+
8
+ def self.bracket_header_to_dash_header(bracket_header)
9
+ # e.g. replace occurrences of '[1]' with '-1'
10
+ bracket_header.gsub(/(\[(\d+)\])/, '-\2')
11
+ end
12
+
13
+ def self.dash_header_to_bracket_header(dash_header)
14
+ # e.g. replace occurrences of '-1' with '[1]'
15
+ dash_header.gsub(/(-(\d+))/, '[\2]')
16
+ end
17
+
18
+ def self.raise_error_if_invalid_array_notation_value!(error_class, array_notation)
19
+ raise error_class, "Invalid array notation. Must be one of #{VALID_ARRAY_NOTATIONS.join(' or ')}." unless VALID_ARRAY_NOTATIONS.include?(array_notation)
20
+ end
21
+
22
+ end
23
+ end
@@ -1,3 +1,5 @@
1
+ require 'json_csv/array_notation'
2
+ require 'json_csv/utils'
1
3
  require 'csv'
2
4
 
3
5
  module JsonCsv
@@ -13,19 +15,33 @@ module JsonCsv
13
15
  # presenting that row as un-flattened json.
14
16
  # This method works for large CSVs and uses very little memory
15
17
  # because it only keeps one row in memory at a time.
16
- def csv_file_to_hierarchical_json_hash(path_to_csv, field_casting_rules = {})
18
+ def csv_file_to_hierarchical_json_hash(path_to_csv, field_casting_rules = {}, array_notation = JsonCsv::ArrayNotation::BRACKETS, strip_value_whitespace = true)
17
19
  i = 0
18
- CSV.foreach(path_to_csv, headers: true) do |row_data_hash|
19
- hierarchical_hash = {}
20
- row_data_hash.each do |key, value|
21
- next if value.nil? || value == '' # ignore nil or empty string values
22
- put_value_at_json_path(hierarchical_hash, key, value, field_casting_rules)
20
+ CSV.foreach(path_to_csv, headers: true, header_converters: lambda { |header|
21
+ if array_notation == JsonCsv::ArrayNotation::DASH
22
+ JsonCsv::ArrayNotation.dash_header_to_bracket_header(header).strip
23
+ else
24
+ header.strip
23
25
  end
24
- yield hierarchical_hash, i
26
+ }) do |row_data_hash|
27
+ yield csv_row_hash_to_hierarchical_json_hash(row_data_hash, field_casting_rules, strip_value_whitespace), i
25
28
  i += 1
26
29
  end
27
30
  end
28
31
 
32
+ def csv_row_hash_to_hierarchical_json_hash(row_data_hash, field_casting_rules, strip_value_whitespace = true)
33
+ hierarchical_hash = {}
34
+ row_data_hash.each do |key, value|
35
+ next if value.nil? || value == '' # ignore nil or empty string values
36
+ put_value_at_json_path(hierarchical_hash, key, value, field_casting_rules)
37
+ end
38
+ # Clean up empty array elements, which may have come about from CSV data
39
+ # that was 1-indexed instead of 0-indexed.
40
+ JsonCsv::Utils.recursively_remove_blank_fields!(hierarchical_hash)
41
+ JsonCsv::Utils.recursively_strip_value_whitespace!(hierarchical_hash) if strip_value_whitespace
42
+ hierarchical_hash
43
+ end
44
+
29
45
  # For the given obj, puts the given value at the given json_path,
30
46
  # creating nested elements as needed. This method calls itself
31
47
  # recursively when placing a value at a nested path, and during
@@ -7,11 +7,16 @@ module JsonCsv
7
7
  # strings (because CSVs are dumb and don't store info about data types)
8
8
  # Set first_index to 1 if you want the first element in an array to
9
9
  #
10
- def json_hash_to_flat_csv_row_hash(json_hash)
10
+ def json_hash_to_flat_csv_row_hash(json_hash, array_notation = JsonCsv::ArrayNotation::BRACKETS)
11
11
  flat = flatten_hash(json_hash)
12
12
  # Convert values to strings because in the CSV file, all values are strings
13
13
  flat.each { |key, val| flat[key] = val.nil? ? '' : val.to_s }
14
- flat
14
+ # If we're using dash array notation, convert the headers
15
+ if array_notation == JsonCsv::ArrayNotation::DASH
16
+ Hash[flat.map { |key, val| [JsonCsv::ArrayNotation.bracket_header_to_dash_header(key), val] }]
17
+ else
18
+ flat
19
+ end
15
20
  end
16
21
 
17
22
  # This method calls itself recursively while flattening a hash, and during
@@ -20,7 +25,7 @@ module JsonCsv
20
25
  if obj.is_a?(Hash)
21
26
  obj.each do |key, val|
22
27
  if key_contains_unallowed_characters?(key)
23
- raise ArgumentError, 'Cannot deal with hash keys that contain "[" or "]" because these are used for internal processing.'
28
+ raise ArgumentError, 'Cannot deal with hash keys that contain "[" or "]" or "." because these characters have special meanings in CSV headers.'
24
29
  end
25
30
  path = parent_path + (parent_path.empty? ? '' : '.') + key
26
31
  flatten_hash(val, path, flat_hash_to_build)
@@ -0,0 +1,64 @@
1
+ module JsonCsv
2
+ module Utils
3
+
4
+ # Returns true for empty strings, empty arrays, or empty hashes.
5
+ # Also returns true for strings that only contain whitespace.
6
+ # Returns false for all other values, including booleans and numbers.
7
+ def self.removable_value?(value)
8
+ return true if value.respond_to?(:empty?) && value.empty? # empty string, empty array, or empty hash
9
+ return true if value.is_a?(String) && value.strip.empty? # string that only contains whitespace
10
+ return true if value.nil?
11
+ false
12
+ end
13
+
14
+ def self.recursively_remove_blank_fields!(hash_or_array)
15
+ return if hash_or_array.frozen? # We can't modify a frozen value, so we won't.
16
+
17
+ if hash_or_array.is_a?(Array)
18
+ # Recurse through non-empty elements
19
+ hash_or_array.each do |element|
20
+ recursively_remove_blank_fields!(element) if element.is_a?(Hash) || element.is_a?(Array)
21
+ end
22
+
23
+ # Delete blank array element values on this array level (including empty object ({}) values)
24
+ hash_or_array.delete_if do |element|
25
+ removable_value?(element)
26
+ end
27
+ elsif hash_or_array.is_a?(Hash)
28
+ hash_or_array.each_value do |value|
29
+ recursively_remove_blank_fields!(value) if value.is_a?(Hash) || value.is_a?(Array)
30
+ end
31
+
32
+ # Delete blank hash values on this hash level (including empty object ({}) values)
33
+ hash_or_array.delete_if do |_key, value|
34
+ removable_value?(value)
35
+ end
36
+ else
37
+ raise ArgumentError, 'Must supply a hash or array.'
38
+ end
39
+
40
+ hash_or_array
41
+ end
42
+
43
+ # Recursively goes through an object and strips whitespace,
44
+ # modifying the object's nested child hashes or array.
45
+ # Note: This method modifies hash values, but does not
46
+ # modify hash keys.
47
+ def self.recursively_strip_value_whitespace!(obj)
48
+ if obj.is_a?(Array)
49
+ obj.each do |element|
50
+ recursively_strip_value_whitespace!(element)
51
+ end
52
+ elsif obj.is_a?(Hash)
53
+ obj.each_value do |value|
54
+ recursively_strip_value_whitespace!(value)
55
+ end
56
+ elsif obj.is_a?(String)
57
+ obj.strip!
58
+ end
59
+
60
+ obj
61
+ end
62
+
63
+ end
64
+ end
@@ -1,6 +1,6 @@
1
1
  module JsonCsv
2
2
 
3
- VERSION = '0.0.5'.freeze
3
+ VERSION = '0.0.6'.freeze
4
4
 
5
5
  def self.version
6
6
  VERSION
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: json_csv
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric O'Hanlon
@@ -88,8 +88,10 @@ extra_rdoc_files: []
88
88
  files:
89
89
  - README.md
90
90
  - lib/json_csv.rb
91
+ - lib/json_csv/array_notation.rb
91
92
  - lib/json_csv/csv_to_json.rb
92
93
  - lib/json_csv/json_to_csv.rb
94
+ - lib/json_csv/utils.rb
93
95
  - lib/json_csv/version.rb
94
96
  - lib/tasks/json_csv.rake
95
97
  - lib/tasks/json_csv/ci.rake