Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to serialize Exception

Tags:

ruby

According to ruby-doc and apidock, you can serialize and deserialize an exception using to_json and json_create.

But after having wasted some time trying to use them, I still haven't found a way.

Calling exc.to_json gives me an empty hash, and Exception.json_create(hash) gives me this error: undefined method 'json_create' for Exception:Class

I guess I could easily recreate those functions since the source is available, but I'd rather understand what I'm doing wrong... Any idea?

like image 769
user3033467 Avatar asked May 27 '16 17:05

user3033467


People also ask

When to use exceptions instead of serialization?

More specifically, when the exception contains custom objects which may or may not themselves be serializable.

What is NotSerializableException in Java?

Incase, if an object contains variables of class type that refer to objects whose classes are not serializable, the object stream methods will NotSerializableException when attempting to write or read an instance. Even ,when a collection is serializable but contains objects that are not serializable, an exception will be show.

What happens if a collection contains objects that are not serializable?

Even ,when a collection is serializable but contains objects that are not serializable, an exception will be show. If that field refers to an instance of a serializable class, no exception occurs upon serialization.

Is the [Serializable] attribute alone enough?

The [Serializable] attribute alone is not enough — Exception implements ISerializable which means your derived classes must also implement custom serialization. This involves two steps:


3 Answers

The JSON module doesn't extend Exception by default. You have to require "json/add/exception". I'm not sure if this is documented anywhere:

require "json/add/exception"

begin
  nil.foo
rescue => exception
  ex = exception
end

puts ex.to_json
# => {"json_class":"NoMethodError","m":"undefined method `foo' for nil:NilClass","b":["prog.rb:5:in `<main>'"]}

Check out ext/json/lib/json/add in the Ruby source to see which classes work this way. If you do require "json/add/core" it will load JSON extensions for Date, DateTime, Exception, OpenStruct, Range, Regexp, Struct, Symbol, Time, and others.

like image 190
Jordan Running Avatar answered Oct 13 '22 12:10

Jordan Running


The answer from Jordan is correct. If you have a case eg. that you need to serialize an Exception and send to to ActiveJob where you want to reconstruct it, then you need to use .as_json method.

require "json/add/exception"

begin
  nil.foo
rescue => exception
  ex = exception
end

puts ex.to_json.class
# => String

string = ex.to_json
puts Exception.json_create(string).message
# => m

puts ex.as_json.class
# => Hash

hash = ex.as_json
puts Exception.json_create(hash).message
# => undefined method `foo' for nil:NilClass

You need to read the source code to understand why Exception.json_create(string).messagereturns m :)

like image 40
talakoski Avatar answered Oct 13 '22 10:10

talakoski


It's also important to note that the Exception.json_create example doesn't keep the error class.

Exception.json_create(JSON.parse(ArgumentError.new('error').to_json))
# => #<Exception: error>

Try instead:

require "json/add/exception"

def deserialize_exception(json)
  hash = JSON.parse(json)
  hash['json_class'].constantize.json_create(hash)
end
like image 42
thisismydesign Avatar answered Oct 13 '22 12:10

thisismydesign