-
Notifications
You must be signed in to change notification settings - Fork 4.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support of serdes for Throwable/Exception no longer works since Java 17 #2352
Comments
Have added the "enhancement" label because there was never really proper support for Backward compatibility might also be a (small) problem: If Gson added now a type adapter factory which handles Most likely it is also not possible to properly support deserialization because exceptions can have arbitrary constructors (which might make adjustments to the provided message), so even if Gson was able to create an instance of an exception, the instance would most likely not be identical to the original one. Note that I am not a direct member of this project, but my opinion is that users should write their own adapter, and include all information they consider important. Here is an example for including the type name, the message, the cause and suppressed exceptions: class ThrowableAdapterFactory implements TypeAdapterFactory {
private ThrowableAdapterFactory() {}
public static final ThrowableAdapterFactory INSTANCE = new ThrowableAdapterFactory();
@Override
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
// Only handles Throwable and subclasses; let other factories handle any other type
if (!Throwable.class.isAssignableFrom(type.getRawType())) {
return null;
}
@SuppressWarnings("unchecked")
TypeAdapter<T> adapter = (TypeAdapter<T>) new TypeAdapter<Throwable>() {
@Override
public Throwable read(JsonReader in) throws IOException {
throw new UnsupportedOperationException();
}
@Override
public void write(JsonWriter out, Throwable value) throws IOException {
if (value == null) {
out.nullValue();
return;
}
out.beginObject();
// Include exception type name to give more context; for example NullPointerException might
// not have a message
out.name("type");
out.value(value.getClass().getSimpleName());
out.name("message");
out.value(value.getMessage());
Throwable cause = value.getCause();
if (cause != null) {
out.name("cause");
write(out, cause);
}
Throwable[] suppressedArray = value.getSuppressed();
if (suppressedArray.length > 0) {
out.name("suppressed");
out.beginArray();
for (Throwable suppressed : suppressedArray) {
write(out, suppressed);
}
out.endArray();
}
out.endObject();
}
};
return adapter;
}
} And then register it like this: new GsonBuilder()
.registerTypeAdapterFactory(ThrowableAdapterFactory.INSTANCE)
.create() Edit: You could probably also simplify this to only write a |
Thank you @Marcono1234 I appreciate the explanation and code sample. I see this would be messy now that you mentioned the deserialization side of the issue. BTW, is there an easier (more relaxed) way to register user customized adapters? For example, the Adapter interface has both read and write methods but I see little reason to force the user to implement both if they only need either serialization or deserialization. Wouldn't being able to register serializer/writer and deserializer/reader separately more convenient? |
There are the separate interfaces The easiest solution would probably be to implement Footnotes
|
Failure Message: "com.google.gson.JsonIOException: Failed making field 'java.lang.Throwable#detailMessage' accessible; either increase its visibility or write a custom TypeAdapter for its declaring type. ... Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make field private java.lang.String java.lang.Throwable.detailMessage accessible: module java.base does not "opens java.lang" to unnamed module @7b36aa0c" Explanation: "This is most probably due to the fact that support for throwable/exception no longer works since Java 17." For more info see: google/gson#2352
Failure Message: "com.google.gson.JsonIOException: Failed making field 'java.lang.Throwable#detailMessage' accessible; either increase its visibility or write a custom TypeAdapter for its declaring type. ... Caused by: java.lang.reflect.InaccessibleObjectException: Unable to make field private java.lang.String java.lang.Throwable.detailMessage accessible: module java.base does not "opens java.lang" to unnamed module @7b36aa0c" Explanation: "This is most probably due to the fact that support for throwable/exception no longer works since Java 17." For more info see: google/gson#2352
Gson version
2.10.1
Java / Android version
17.0.6 Amazon Corretto
Used tools
Description
Expected behavior
Gson should serialize the ExBean instance with the Throwable field, with stack trace details and related info on the Exception.
Actual behavior
Gson.toJson errors out with exception. See stack trace below.
Reproduction steps
Exception stack trace
The text was updated successfully, but these errors were encountered: