From 6f86245ab48471d8e3801dd4195f50d388230361 Mon Sep 17 00:00:00 2001 From: Fabio Perrella Date: Wed, 8 Jul 2020 17:57:40 -0300 Subject: [PATCH] Change #as_json adding the option stringify_keys to it --- CHANGELOG.md | 3 +++ README.md | 13 ++++++++++++- lib/attributes_json.rb | 10 +++++++++- lib/format_parser/version.rb | 2 +- spec/attributes_json_spec.rb | 26 ++++++++++++++++++++++++++ spec/parsers/mp3_parser_spec.rb | 28 ++++++++++++++++++++++++++++ 6 files changed, 79 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 350ab89e..4c1f65b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +## 0.22.0 +* Adds option `stringify_keys: true` to #as_json methods (fix #151) + ## 0.21.1 * MPEG: Ensure parsing does not inadvertently return an Integer instead of Result|nil * MPEG: Scan further into the MPEG file than previously (scan 32 1KB chunks) diff --git a/README.md b/README.md index 980b4787..2098fa1f 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,17 @@ img_info = FormatParser.parse(File.open("myimage.jpg", "rb")) JSON.pretty_generate(img_info) #=> ... ``` +To convert the result to a Hash + +```ruby +img_info = FormatParser.parse(File.open("myimage.jpg", "rb")) +img_info.as_json + +# it's also possible to convert all keys to string +img_info.as_json(stringify_keys: true) +``` + + ## Creating your own parsers See the [section on writing parsers in CONTRIBUTING.md](CONTRIBUTING.md#so-you-want-to-contribute-a-new-parser) @@ -188,7 +199,7 @@ Unless specified otherwise in this section the fixture files are MIT licensed an ## Copyright -Copyright (c) 2019 WeTransfer. +Copyright (c) 2020 WeTransfer. `format_parser` is distributed under the conditions of the [Hippocratic License](https://firstdonoharm.dev/version/1/2/license.html) - See LICENSE.txt for further details. diff --git a/lib/attributes_json.rb b/lib/attributes_json.rb index b2bd9d79..9f42b402 100644 --- a/lib/attributes_json.rb +++ b/lib/attributes_json.rb @@ -15,7 +15,12 @@ module FormatParser::AttributesJSON # Implements a sane default `as_json` for an object # that accessors defined - def as_json(root: false) + # + # @param root[Bool] if true, it surrounds the result in a hash with a key + # `format_parser_file_info` + # @param stringify_keys[Bool] if true, it transforms all the hash keys to a string. + # The default value is false for backward compatibility + def as_json(root: false, stringify_keys: false, **) h = {} h['nature'] = nature if respond_to?(:nature) # Needed for file info structs methods.grep(/\w\=$/).each_with_object(h) do |attr_writer_method_name, h| @@ -27,6 +32,9 @@ def as_json(root: false) sanitized_value = _sanitize_json_value(unwrapped_attribute_value) h[reader_method_name] = sanitized_value end + + h = FormatParser::HashUtils.deep_transform_keys(h, &:to_s) if stringify_keys + if root {'format_parser_file_info' => h} else diff --git a/lib/format_parser/version.rb b/lib/format_parser/version.rb index 58f3a9ad..1a6d4955 100644 --- a/lib/format_parser/version.rb +++ b/lib/format_parser/version.rb @@ -1,3 +1,3 @@ module FormatParser - VERSION = '0.21.1' + VERSION = '0.22.0' end diff --git a/spec/attributes_json_spec.rb b/spec/attributes_json_spec.rb index 326ac2f8..83fce336 100644 --- a/spec/attributes_json_spec.rb +++ b/spec/attributes_json_spec.rb @@ -140,4 +140,30 @@ def nature JSON.pretty_generate(object_with_attributes_module) }.to raise_error(/structure too deep/) end + + it 'converts all hash keys to string when stringify_keys: true' do + fixture_path = fixtures_dir + '/ZIP/arch_few_entries.zip' + fi_io = File.open(fixture_path, 'rb') + + result = FormatParser::ZIPParser.new.call(fi_io).as_json(stringify_keys: true) + + result['entries'].each do |entry| + entry.each do |key, _value| + expect(key).to be_a(String) + end + end + end + + it 'does not convert hash keys to string when stringify_keys: false' do + fixture_path = fixtures_dir + '/ZIP/arch_few_entries.zip' + fi_io = File.open(fixture_path, 'rb') + + result = FormatParser::ZIPParser.new.call(fi_io).as_json + + result['entries'].each do |entry| + entry.each do |key, _value| + expect(key).to be_a(Symbol) + end + end + end end diff --git a/spec/parsers/mp3_parser_spec.rb b/spec/parsers/mp3_parser_spec.rb index 2441944b..6246f381 100644 --- a/spec/parsers/mp3_parser_spec.rb +++ b/spec/parsers/mp3_parser_spec.rb @@ -110,4 +110,32 @@ subject.call(StringIO.new('')) }.to raise_error(FormatParser::IOUtils::InvalidRead) end + + describe '#as_json' do + it 'converts all hash keys to string when stringify_keys: true' do + fpath = fixtures_dir + '/MP3/Cassy.mp3' + result = subject.call(File.open(fpath, 'rb')).as_json(stringify_keys: true) + + expect( + result['intrinsics'].keys.map(&:class).uniq + ).to eq([String]) + + expect( + result['intrinsics']['id3tags'].map(&:class).uniq + ).to eq([ID3Tag::Tag]) + end + + it 'does not convert the hash keys to string when stringify_keys: false' do + fpath = fixtures_dir + '/MP3/Cassy.mp3' + result = subject.call(File.open(fpath, 'rb')).as_json + + expect( + result['intrinsics'].keys.map(&:class).uniq + ).to eq([Symbol]) + + expect( + result['intrinsics'][:id3tags].map(&:class).uniq + ).to eq([ID3Tag::Tag]) + end + end end