diff -pruN 1.1.3-1/.github/workflows/ruby.yml 2.0.0-1/.github/workflows/ruby.yml
--- 1.1.3-1/.github/workflows/ruby.yml	1970-01-01 00:00:00.000000000 +0000
+++ 2.0.0-1/.github/workflows/ruby.yml	2025-01-04 02:49:21.000000000 +0000
@@ -0,0 +1,38 @@
+# This workflow uses actions that are not certified by GitHub.
+# They are provided by a third-party and are governed by
+# separate terms of service, privacy policy, and support
+# documentation.
+# This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
+# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
+
+name: Ruby
+
+on:
+  push:
+    branches: [ "main" ]
+  pull_request:
+    branches: [ "main" ]
+
+permissions:
+  contents: read
+
+jobs:
+  test:
+
+    runs-on: ubuntu-latest
+    strategy:
+      matrix:
+        ruby-version: ['3.1', '3.2', '3.3', head, jruby, jruby-head]
+
+    steps:
+    - uses: actions/checkout@v4
+    - name: Set up Ruby
+    # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby,
+    # change this to (see https://github.com/ruby/setup-ruby#versioning):
+    # uses: ruby/setup-ruby@v1
+      uses: ruby/setup-ruby@943103cae7d3f1bb1e4951d5fcc7928b40e4b742 # 1.177.1
+      with:
+        ruby-version: ${{ matrix.ruby-version }}
+        bundler-cache: true # runs 'bundle install' and caches installed gems automatically
+    - name: Run tests
+      run: bundle exec rake
diff -pruN 1.1.3-1/.travis.yml 2.0.0-1/.travis.yml
--- 1.1.3-1/.travis.yml	2020-12-01 23:01:27.000000000 +0000
+++ 2.0.0-1/.travis.yml	2025-01-04 02:49:21.000000000 +0000
@@ -11,7 +11,8 @@ rvm:
   # Current stable supported by Travis
   - 2.5.8
   - 2.6.6
-  - 2.7.1
+  - 2.7.2
+  - 3.0.0
   - jruby-9.1.9.0
   # Future
   - ruby-head
diff -pruN 1.1.3-1/AUTHORS.txt 2.0.0-1/AUTHORS.txt
--- 1.1.3-1/AUTHORS.txt	2020-12-01 23:01:27.000000000 +0000
+++ 2.0.0-1/AUTHORS.txt	2025-01-04 02:49:21.000000000 +0000
@@ -8,18 +8,24 @@ Recursive-open-struct was written by the
 * Ewoud Kohl van Wijngaarden <ewoud@kohlvanwijngaarden.nl>
 * Federico Aloi <federico.aloi@gmail.com>
 * fervic <roberto@runawaybit.com>
+* Hartley McGuire <skipkayhil@gmail.com>
 * Igor Victor <gogainda@yandex.ru>
+* Ilya Umanets <ilya.umanets@sabiogroup.com>
 * Jean Boussier <jean.boussier@gmail.com>
 * Joe Rafaniello <jrafanie@redhat.com>
 * Kris Dekeyser <kris.dekeyser@libis.be>
+* Maple Ong <maple.ong@gusto.com>
 * Matt Culpepper <matt@culpepper.co>
 * Matthew O'Riordan <matthew.oriordan@gmail.com>
 * Offirmo <offirmo.net@gmail.com>
 * Pedro Sena <sena.pedro@gmail.com>
 * Peter Yeremenko <peter.yeremenko@gmail.com>
 * Pirate Praveen <praveen@debian.org>
+* Richard Degenne <richard.degenne+github@gmail.com>
+* Richard Degenne <richard.degenne@gmail.com>
 * Sebastian Gaul <sebastian@mgvmedia.com>
 * Thiago Guimaraes <thiagogsr@gmail.com>
 * Tom Chapin <tchapin@gmail.com>
 * Victor Guzman <victor.guzman@runawaybit.com>
 * William (B.J.) Snow Orvis <aetherknight@gmail.com>
+* Wynn (B.J.) Snow Orvis <aetherknight@gmail.com>
diff -pruN 1.1.3-1/CHANGELOG.md 2.0.0-1/CHANGELOG.md
--- 1.1.3-1/CHANGELOG.md	2020-12-01 23:01:27.000000000 +0000
+++ 2.0.0-1/CHANGELOG.md	2025-01-04 02:49:21.000000000 +0000
@@ -1,3 +1,47 @@
+2.0.0 / 2024/10/03
+==================
+
+* BREAKING: Restore #72, which is an API-breaking change because it changes
+  what data is serialized with marshalling.
+
+1.3.1 / 2024/10/03
+==================
+
+* FIX for
+  [#79](https://github.com/aetherknight/recursive-open-struct/issues/79):
+  Revert #72's change to marshalling and dumping since it is an API-breaking
+  change. It will be re-added in a new major version after releasing a fix.
+
+1.3.0 / 2024/10/01
+==================
+
+* [#72](https://github.com/aetherknight/recursive-open-struct/pull/72): Maple
+  Ong: Better handle marshalling and dumping ROS
+* [#78](https://github.com/aetherknight/recursive-open-struct/pull/78): Hartley
+  McGuire: Add ostruct as a dependency since newer Ruby versions are going to
+  remove it
+
+1.2.2 / 2024/06/18
+==================
+
+* [#75](https://github.com/aetherknight/recursive-open-struct/pull/75): Richard
+  Degenne: Fix Ruby 3.1 `#freeze`
+
+1.2.1 / 2024/05/27
+==================
+
+* Fix a test that is flakey with JRuby
+
+1.2.0 / 2024/05/27
+==================
+
+* [#76](https://github.com/aetherknight/recursive-open-struct/pull/76):
+  IlyaUmanets: Add `raise_on_missing` option, causing ROS to raise
+  `NoMethodError` instead of returning `nil` if a field doesn't exist
+* MAINT: Switched to Github Actions for CI
+* MAINT: No longer officially supporting Ruby versions of 3.0.x or earlier,
+  updated CI to test 3.1.x, 3.2.x, 3.3.x
+
 1.1.3 / 2020/10/15
 ==================
 
diff -pruN 1.1.3-1/README.md 2.0.0-1/README.md
--- 1.1.3-1/README.md	2020-12-01 23:01:27.000000000 +0000
+++ 2.0.0-1/README.md	2025-01-04 02:49:21.000000000 +0000
@@ -62,6 +62,23 @@ ros = RecursiveOpenStruct.new(h, preserv
 ros.to_h # => { 'fear' => 'is', 'the' => 'mindkiller' }
 ```
 
+### Optional: Raise error on missing attribute
+
+This option allows to raise an error if you try to call an attribute you didn't specify in hash
+
+```ruby
+h = { 'fear' => 'is', 'the' => 'mindkiller' } }
+ros = RecursiveOpenStruct.new(h, raise_on_missing: true)
+ros.undefined # => undefined method `undefined' for #<RecursiveOpenStruct fear="is", the="mindkiller">
+```
+
+The default behaviour returns nil
+
+```ruby
+h = { 'fear' => 'is', 'the' => 'mindkiller' } }
+ros = RecursiveOpenStruct.new(h)
+ros.undefined # => nil
+```
 
 ## Installation
 
diff -pruN 1.1.3-1/debian/changelog 2.0.0-1/debian/changelog
--- 1.1.3-1/debian/changelog	2021-11-24 20:26:33.000000000 +0000
+++ 2.0.0-1/debian/changelog	2025-10-25 15:52:18.000000000 +0000
@@ -1,3 +1,12 @@
+ruby-recursive-open-struct (2.0.0-1) unstable; urgency=medium
+
+  * Team upload.
+  * New upstream release.
+  * Drop {XS,XB}-Ruby-Versions from control.
+  * Update Standards-Version to 4.7.2, no changes needed.
+
+ -- Simon Quigley <tsimonq2@debian.org>  Sat, 25 Oct 2025 10:52:18 -0500
+
 ruby-recursive-open-struct (1.1.3-1) unstable; urgency=medium
 
   * Team upload.
diff -pruN 1.1.3-1/debian/control 2.0.0-1/debian/control
--- 1.1.3-1/debian/control	2021-11-24 20:26:33.000000000 +0000
+++ 2.0.0-1/debian/control	2025-10-25 15:50:42.000000000 +0000
@@ -8,20 +8,19 @@ Build-Depends: debhelper-compat (= 13),
                pry,
                rake,
                ruby-rspec
-Standards-Version: 4.6.0
+Standards-Version: 4.7.2
 Vcs-Git: https://salsa.debian.org/ruby-team/ruby-recursive-open-struct.git
 Vcs-Browser: https://salsa.debian.org/ruby-team/ruby-recursive-open-struct
 Homepage: https://github.com/aetherknight/recursive-open-struct
 Testsuite: autopkgtest-pkg-ruby
-XS-Ruby-Versions: all
 Rules-Requires-Root: no
 
 Package: ruby-recursive-open-struct
 Architecture: all
-XB-Ruby-Versions: ${ruby:Versions}
 Depends: ${misc:Depends},
          ${ruby:Depends},
          ${shlibs:Depends}
+Multi-Arch: foreign
 Description: OpenStruct subclass that returns nested hash attributes as RecursiveOpenStructs
  RecursiveOpenStruct is a subclass of OpenStruct. It differs from
  OpenStruct in that it allows nested hashes to be treated in a recursive
diff -pruN 1.1.3-1/debian/gbp.conf 2.0.0-1/debian/gbp.conf
--- 1.1.3-1/debian/gbp.conf	1970-01-01 00:00:00.000000000 +0000
+++ 2.0.0-1/debian/gbp.conf	2025-10-25 15:49:06.000000000 +0000
@@ -0,0 +1,4 @@
+[DEFAULT]
+debian-branch = debian/latest
+upstream-branch = upstream/latest
+pristine-tar = True
diff -pruN 1.1.3-1/debian/salsa-ci.yml 2.0.0-1/debian/salsa-ci.yml
--- 1.1.3-1/debian/salsa-ci.yml	2021-11-24 20:26:33.000000000 +0000
+++ 2.0.0-1/debian/salsa-ci.yml	2025-10-25 15:49:06.000000000 +0000
@@ -1,4 +1,3 @@
 ---
 include:
-  - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/salsa-ci.yml
-  - https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/pipeline-jobs.yml
+  - https://salsa.debian.org/ruby-team/meta/raw/master/salsa-ci.yml
diff -pruN 1.1.3-1/lib/recursive_open_struct/version.rb 2.0.0-1/lib/recursive_open_struct/version.rb
--- 1.1.3-1/lib/recursive_open_struct/version.rb	2020-12-01 23:01:27.000000000 +0000
+++ 2.0.0-1/lib/recursive_open_struct/version.rb	2025-01-04 02:49:21.000000000 +0000
@@ -3,5 +3,5 @@
 require 'ostruct'
 
 class RecursiveOpenStruct < OpenStruct
-  VERSION = "1.1.3"
+  VERSION = "2.0.0"
 end
diff -pruN 1.1.3-1/lib/recursive_open_struct.rb 2.0.0-1/lib/recursive_open_struct.rb
--- 1.1.3-1/lib/recursive_open_struct.rb	2020-12-01 23:01:27.000000000 +0000
+++ 2.0.0-1/lib/recursive_open_struct.rb	2025-01-04 02:49:21.000000000 +0000
@@ -23,7 +23,8 @@ class RecursiveOpenStruct < OpenStruct
     {
       mutate_input_hash: false,
       recurse_over_arrays: false,
-      preserve_original_keys: false
+      preserve_original_keys: false,
+      raise_on_missing: false
     }
   end
 
@@ -39,6 +40,16 @@ class RecursiveOpenStruct < OpenStruct
     @sub_elements = {}
   end
 
+  def marshal_load(attributes)
+    hash, @options = attributes
+    @deep_dup = DeepDup.new(@options)
+    @sub_elements = {}
+    super(hash)
+  end
+
+  def marshal_dump
+    [super, @options]
+  end
 
   if OpenStruct.public_instance_methods.include?(:initialize_copy)
     def initialize_copy(orig)
@@ -124,6 +135,10 @@ class RecursiveOpenStruct < OpenStruct
       if @table.key?(_get_key_from_table_(key))
         new_ostruct_member!(key)
         public_send(mid)
+      elsif @options[:raise_on_missing]
+        err = NoMethodError.new "undefined method `#{mid}' for #{self}", mid, args
+        err.set_backtrace caller(1)
+        raise err
       end
     else
       err = NoMethodError.new "undefined method `#{mid}' for #{self}", mid, args
@@ -132,6 +147,14 @@ class RecursiveOpenStruct < OpenStruct
     end
   end
 
+  def freeze
+    @table.each_key do |key|
+      new_ostruct_member!(key)
+    end
+
+    super
+  end
+
   # TODO: Rename to new_ostruct_member! once we care less about Rubies before
   # 2.4.0.
   def new_ostruct_member(name)
diff -pruN 1.1.3-1/recursive-open-struct.gemspec 2.0.0-1/recursive-open-struct.gemspec
--- 1.1.3-1/recursive-open-struct.gemspec	2020-12-01 23:01:27.000000000 +0000
+++ 2.0.0-1/recursive-open-struct.gemspec	2025-01-04 02:49:21.000000000 +0000
@@ -40,5 +40,7 @@ Gem::Specification.new do |s|
   s.add_development_dependency('rdoc', [">= 0"])
   s.add_development_dependency('rspec', "~> 3.2")
   s.add_development_dependency('simplecov', [">= 0"])
+
+  s.add_dependency('ostruct')
 end
 
diff -pruN 1.1.3-1/spec/recursive_open_struct/indifferent_access_spec.rb 2.0.0-1/spec/recursive_open_struct/indifferent_access_spec.rb
--- 1.1.3-1/spec/recursive_open_struct/indifferent_access_spec.rb	2020-12-01 23:01:27.000000000 +0000
+++ 2.0.0-1/spec/recursive_open_struct/indifferent_access_spec.rb	2025-01-04 02:49:21.000000000 +0000
@@ -160,6 +160,30 @@ describe RecursiveOpenStruct do
         end
       end
 
+      context 'when undefined method' do
+        context 'when raise_on_missing is enabled' do
+          subject(:recursive) { RecursiveOpenStruct.new(recursive_hash, raise_on_missing: true) }
+          let(:recursive_hash) { {:foo => [ {'bar' => [ { 'foo' => :bar} ] } ] } }
+
+          specify 'raises NoMethodError' do
+            expect {
+              recursive.undefined_method
+            }.to raise_error(NoMethodError)
+          end
+        end
+
+        context 'when raise_on_missing is disabled' do
+          context 'preserves the original keys' do
+            subject(:recursive) { RecursiveOpenStruct.new(recursive_hash) }
+            let(:recursive_hash) { {:foo => [ {'bar' => [ { 'foo' => :bar} ] } ] } }
+
+            specify 'returns nil' do
+              expect(recursive.undefined_method).to be_nil
+            end
+          end
+        end
+      end
+
     end
 
   end
diff -pruN 1.1.3-1/spec/recursive_open_struct/open_struct_behavior_spec.rb 2.0.0-1/spec/recursive_open_struct/open_struct_behavior_spec.rb
--- 1.1.3-1/spec/recursive_open_struct/open_struct_behavior_spec.rb	2020-12-01 23:01:27.000000000 +0000
+++ 2.0.0-1/spec/recursive_open_struct/open_struct_behavior_spec.rb	2025-01-04 02:49:21.000000000 +0000
@@ -108,5 +108,41 @@ describe RecursiveOpenStruct do
         it { expect(subject.methods.map(&:to_sym)).to_not include :asdf= }
       end # describe #methods
     end # describe handling of arbitrary attributes
+
+    describe "handling of freezing" do
+      let(:hash) { { :asdf => 'John Smith' } }
+
+      before do
+        ros.freeze
+      end
+
+      it "can read existing keys" do
+        expect(ros.asdf).to eq 'John Smith'
+      end
+
+      it "cannot write new keys" do
+        expect { ros.new_key = 'new_value' }.to raise_error FrozenError
+      end
+
+      it "cannot write existing keys" do
+        expect { ros.asdf = 'new_value' }.to raise_error FrozenError
+      end
+
+      context "with recursive structure" do
+        let(:hash) { { :key => { :subkey => 42 } } }
+
+        it "can read existing sub-elements" do
+          expect(ros.key.subkey).to eq 42
+        end
+
+        it "can write new sub-elements" do
+          expect { ros.key.new_subkey = 43 }.not_to raise_error
+        end
+
+        it "can write existing sub-elements" do
+          expect { ros.key.subkey = 43 }.not_to raise_error
+        end
+      end
+    end
   end # describe behavior it inherits from OpenStruct
 end
diff -pruN 1.1.3-1/spec/recursive_open_struct/ostruct_2_0_0_spec.rb 2.0.0-1/spec/recursive_open_struct/ostruct_2_0_0_spec.rb
--- 1.1.3-1/spec/recursive_open_struct/ostruct_2_0_0_spec.rb	2020-12-01 23:01:27.000000000 +0000
+++ 2.0.0-1/spec/recursive_open_struct/ostruct_2_0_0_spec.rb	2025-01-04 02:49:21.000000000 +0000
@@ -89,7 +89,7 @@ describe RecursiveOpenStruct do
 
     context "hash" do
       it "calculates table hash" do
-        expect(ros.hash).to be ros.instance_variable_get('@table').hash
+        expect(ros.hash).to eq(ros.instance_variable_get('@table').hash)
       end
 
     end
diff -pruN 1.1.3-1/spec/recursive_open_struct/recursion_spec.rb 2.0.0-1/spec/recursive_open_struct/recursion_spec.rb
--- 1.1.3-1/spec/recursive_open_struct/recursion_spec.rb	2020-12-01 23:01:27.000000000 +0000
+++ 2.0.0-1/spec/recursive_open_struct/recursion_spec.rb	2025-01-04 02:49:21.000000000 +0000
@@ -37,6 +37,14 @@ describe RecursiveOpenStruct do
       expect(ros.blah.changed).to eql 'backing'
     end
 
+    it "handles being dump then loaded by Marshal" do
+      foo_struct = [RecursiveOpenStruct.new]
+      bar_struct = RecursiveOpenStruct.new(foo: foo_struct)
+      serialized = Marshal.dump(bar_struct)
+
+      expect(Marshal.load(serialized).foo).to eq(foo_struct)
+    end
+
     describe "handling loops in the original Hashes" do
       let(:h1) { { :a => 'a'} }
       let(:h2) { { :a => 'b', :h1 => h1 } }
@@ -182,6 +190,17 @@ describe RecursiveOpenStruct do
       let(:blah_list) { [ { :foo => '1' }, { :foo => '2' }, 'baz' ] }
       let(:h) { { :blah => blah_list } }
 
+      context "when dump and loaded by Marshal" do
+        let(:test) { RecursiveOpenStruct.new(h, :recurse_over_arrays => true) }
+        subject { Marshal.load(Marshal.dump(test))}
+
+        it { expect(subject.blah.length).to eq 3 }
+        it { expect(subject.blah[0].foo).to eq '1' }
+        it { expect(subject.blah[1].foo).to eq '2' }
+        it { expect(subject.blah_as_a_hash).to eq blah_list }
+        it { expect(subject.blah[2]).to eq 'baz' }
+      end
+
       context "when recursing over arrays is enabled" do
         subject { RecursiveOpenStruct.new(h, :recurse_over_arrays => true) }
 
