Repository navigation
Wish: Remove "forced" dependency from ostruct #988
Description
Activity
I'll remove the dependency and see if that breaks anything. It might be an issue with earlier ruby versions.
I am running ruby 4.0.1 and got this warning when I upgraded OJ to 3.16.14:
warning: ostruct used to be loaded from the standard library, but is not part of the default gems since Ruby 4.0.0.
You can add ostruct to your Gemfile or gemspec to fix this error.I just added ostruct to my Gemfile for now.
Reacted by Jonathan Swartz and Ezra JenningsAlso got the same warning on Ruby 3.4 after upgrading to the latest oj release.
It includes the following line. 😇
Also please contact the author of oj-3.16.14 to request adding ostruct into its gemspec.
Historic reference: #928.
Also please contact the author of oj-3.16.14 to request adding ostruct into its gemspec.
FYI: This is only one of the possible options. This wish is about a different approach: to not "actively"
require "ostruct"unconditonally. Hopefully similar to how the standard json gem doesn't require it actively anymore, nowadays. Given ruby core learned thatOpenStructis broken by design and should be avoided. If the "surrounding" ruby code never accessesOpenStruct, it should also not be loaded just becauseojis used.TL;DR: The goal should be:
- for a
Gemfilewithgem oj, and - code that accesses
Oj(Oj.load,Oj.dump,Oj::ParseError) - then still no warning about
ostruct used to be loaded from the standard library.
Whether one needs to add
gem "ostruct"(only) if (e.g.)require "oj/mimic"is called, remains open.
People which accessJSON::GenericObjectactively can likely be expected to provide its prerequisite. And/or it is not anymoreoj's responsibility to provide a copy of the code of thejsongem here.- for a
(hi just another person with the message that popped up for ruby 4)
This wish is about a different approach: to not "actively" require "ostruct" unconditonally. Hopefully similar to how the standard json gem doesn't require it actively anymore, nowadays.
looks like we can catch the LoadError and its already guarded for here:
Line 97 in b0b0171
if Object.const_defined?('OpenStruct') but looks like this might need to be changed:
Line 118 in b0b0171
class GenericObject < OpenStruct Like others, I'm running into the missing ostruct dependency warning here as well. Ruby 3.4.7.
~/.rvm/gems/ruby-3.4.7@main/gems/oj-3.16.14/lib/oj/mimic.rb:4: warning: ~/.rvm/rubies/ruby-3.4.7/lib/ruby/3.4.0/ostruct.rb was loaded from the standard library, but will no longer be part of the default gems starting from Ruby 3.5.0. You can add ostruct to your Gemfile or gemspec to silence this warning. Also please contact the author of oj-3.16.14 to request adding ostruct into its gemspec.@ohler55, as you suggested could happen, dropping ostruct does appear to be an issue with at least some Ruby versions.
This is, at least in part, because
require 'ostruct'happens during default usage of the gem. Note the dependency/require chain:gem 'oj' => bundler calls require 'oj' => oj.rb:11 require 'oj/mimic' => mimic.rb:5 require 'ostruct'That means that
ostructis a default requirement of the gem, same asbigdecimal, becauseoj/mimicis always required.The
ostructgem (v0.6.3) is nearly 500 lines, so it's not just a shim (at least not on all versions of Ruby supported by Oj, which is back to Ruby 2.7). I'm not entirely understanding why ostruct needs to be removed, but perhaps I'm missing something.@phorsuedzie, you wrote "The goal should be ... then still no warning about ostruct used to be loaded from the standard library." Wouldn't this best be solved by indeed making ostruct a dependency, exactly as those warning say?
Regardless, I'd suggest reintroducing the dependency on ostruct for Oj's 3.16.x series, unless it's possible to eliminate all warnings on all of Oj's supported versions of Ruby (2.7..4.0).
Then, if there's a compelling reason to remove ostruct, it either needs to wait until older Rubies are dropped (which I recognize is going to be a while), or Oj needs to detect when the loaded gemspecs are missing 'ostruct' (
if !Gem.loaded_specs['ostruct'] ...perhaps) and then display an error with the specific instruction to addgem 'ostruct'to the app's own Gemfile. I'd argue either of these belongs in a v4 release, or possibly v3.17, depending on semver adherence.PS: @ohler55, been using Oj a long time--thanks for the time and effort you've generously given to all of us these many years.
Ok, reverting back to include the dependency. Will deal with the desire to remove that dependency at a later date.
Reacted by Kairubygems is acting up and not accepting a release push. Oj is tagged though so you are welcome to fetch directly.
Ok, released
Reacted by Julian Boralli, zarqman and Imran IqbalReacted by Imran IqbalOk, released
Just tested, all good. @ohler55 Really appreciate you maintaining Oj.
Reacted by Peter OhlerWouldn't this best be solved by indeed making ostruct a dependency, exactly as those warning say?
With the current implementation, this is what is needed. The actual wish is to be able to use oj with a
Gemfile.lockthat doesn't includeostructanymore (because ruby itself nowadays "dislikes"OpenStructbecause of "questionable design").Which would need to change the implementation, so that it does not anymore
require "ostruct"if oj gets loaded, or that if still does, then it rescues from aLoadError(see ruby's packaged json gem).And maybe one simple solution to not anymore access
OpenStructfrom within this gem's code is to not anymore include a (more or less outdated) copy of the::JSON::GenericObject, but (only then) simplyrequire "json/generic_object", and have the including application care about the (additional) dependencies:jsonandostruct.I'll reopen the issue.
Ruby's core makes some effort to squeeze
ostruct/OpenStructout of the code. The gem 'json', promoted to a default gem now, is no exception to this. Anyrequire "ostruct"there has been transformed into conditional code (see MRI 3.3 => 3.4).OpenStructitself is monkey-patched only with an activerequire 'json/add/ostruct'(see e.g. https://rubyapi.org/3.4/o/openstruct)JSON::GenericObjectis only anautoload. Which works even ifrequire 'ostruct'would raise aLoadError.Best if
Ojwould be able to drops.add_runtime_dependency 'ostruct', '>= 0.2'. And run anyrequire 'ostruct'only if "actively demanded" ...Oj.add_to_json()(if this continues to promise thatOpenStructis patched as a default). Note: ifOpenStructis passed as an argument, there is no need to require it.JSON::GenericObjectis (auto-)loaded. Could even be, that Oj doesn't need to defineJSON::GenericObjectat all anymore (for a modern Ruby). AFAICS, the default json gem'sJSON::GenericObjectisrequire "json", i.e. Oj would have to declare something similar; torequire "json/generic_object"directly works immediately), andgeneric_object.rbcalls nothing but methods fromJSON, which are mimicked byOj(AFAICS).