Skip to content
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

gson.toJson 抛出 java.lang.AssertionError: java.lang.NoSuchFieldException: ONLINE #2038

Closed
1 of 4 tasks
meijieman opened this issue Dec 24, 2021 · 11 comments
Closed
1 of 4 tasks
Labels

Comments

@meijieman
Copy link

meijieman commented Dec 24, 2021

Gson version

com.google.code.gson:gson:2.8.0

Java / Android version

Android 9+as arctic fox

Used tools

  • Maven; version:
  • Gradle; version: api 'com.google.code.gson:gson:2.8.0'
  • ProGuard (attach the configuration file please); version:
  • ...

Description

new Gson().toJsont(object); enter crash.

found into this code
image

why throw new AssertionError(e); , not NoSuchFieldException

Expected behavior

not crash!!!

Actual behavior

crashed !!! even add try-catch(Exception e)

Reproduction steps

  1. ...
  2. ...

Exception stack trace

java.lang.AssertionError: java.lang.NoSuchFieldException: ONLINE
        at com.google.gson.internal.bind.TypeAdapters$EnumTypeAdapter.<init>(TypeAdapters.java:808)
        at com.google.gson.internal.bind.TypeAdapters$30.create(TypeAdapters.java:834)
        at com.google.gson.Gson.getAdapter(Gson.java:423)
        at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.createBoundField(ReflectiveTypeAdapterFactory.java:115)
        at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(ReflectiveTypeAdapterFactory.java:164)
        at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(ReflectiveTypeAdapterFactory.java:100)
        at com.google.gson.Gson.getAdapter(Gson.java:423)
        at com.google.gson.Gson.toJson(Gson.java:661)
        at com.google.gson.Gson.toJson(Gson.java:648)
        at com.google.gson.Gson.toJson(Gson.java:603)
        at com.google.gson.Gson.toJson(Gson.java:583)
        at com.xxx.util.json.JsonUtil.toJson(JsonUtil.java:204)
@meijieman meijieman added the bug label Dec 24, 2021
@meijieman
Copy link
Author

use JSON.toJSONString(object) , output is ok

version: 'com.alibaba:fastjson:1.1.70.android'

@meijieman
Copy link
Author

i update gson to 'com.google.code.gson:gson:2.8.9'
find not crash, but lost some field.

@Marcono1234
Copy link
Collaborator

Could you please verify whether you are using ProGuard? In 2.8.8 an issue with enum constant names and ProGuard usage was fixed (#1495). The AssertionError you are experiencing sounds like that issue.

Most likely obfuscation performed by ProGuard is causing the issues you are seeing. Please either edit your ProGuard config to not obfuscate or shrink your model classes you are using with Gson, or use Gson's @SerializedName annotation to specify the field names, and to not be affected by ProGuard field name obfuscation.


Note that I am not a member of this project.

@meijieman
Copy link
Author

Could you please verify whether you are using ProGuard? In 2.8.8 an issue with enum constant names and ProGuard usage was fixed (#1495). The AssertionError you are experiencing sounds like that issue.

Most likely obfuscation performed by ProGuard is causing the issues you are seeing. Please either edit your ProGuard config to not obfuscate or shrink your model classes you are using with Gson, or use Gson's @SerializedName annotation to specify the field names, and to not be affected by ProGuard field name obfuscation.

Note that I am not a member of this project.

yes, there have enum constant that using ProGuard, but this model classes in third part jar, so i cannot modify this code.
i saw the #1495 , and update to com.google.code.gson:gson:2.8.9 , it's not crash, but leak some of variable。
still have problem。

@Marcono1234
Copy link
Collaborator

It should also be possible to specify ProGuard keep settings for third party libraries, see for example this StackOverflow answer.

However, in general you should be careful when using Gson on third party classes or JDK classes. Gson by default gets private fields of classes, even though the author might not have intended them to be used publicly. This could cause your application to break when the author of the library changes the internal implementation and removes or renames those private fields.
Though, if you only use Gson for an enum class from a third party library, then that is most likely safe because Gson serializes and deserializes the names of the public enum constants.

@meijieman
Copy link
Author

It should also be possible to specify ProGuard keep settings for third party libraries, see for example this StackOverflow answer.

However, in general you should be careful when using Gson on third party classes or JDK classes. Gson by default gets private fields of classes, even though the author might not have intended them to be used publicly. This could cause your application to break when the author of the library changes the internal implementation and removes or renames those private fields. Though, if you only use Gson for an enum class from a third party library, then that is most likely safe because Gson serializes and deserializes the names of the public enum constants.

emmm,first the third party library made ProGuard, not my app, so i can do nothing of obfuscation.
then, i just use Gson#toJson for log it's content. is ok if it Obfuscation.
and i thought is a bug for gson leak variable.(i tried use fastjson, and it work ok.)
i hope gson can fix it.

@Marcono1234
Copy link
Collaborator

i thought is a bug for gson leak variable.(i tried use fastjson, and it work ok.)

Could you please create a small complete example project which can be used to reproduce this with Gson? (And ideally also showing how it correctly works with Fastjson.) Otherwise it is difficult to find out what is causing this issue.

@meijieman
Copy link
Author

i thought is a bug for gson leak variable.(i tried use fastjson, and it work ok.)

Could you please create a small complete example project which can be used to reproduce this with Gson? (And ideally also showing how it correctly works with Fastjson.) Otherwise it is difficult to find out what is causing this issue.

i upload a test project on github. address link: GsonTest
the output log in https://github.com/meijieman/GsonTest/blob/master/REAMDE.md

THX!

@Marcono1234
Copy link
Collaborator

Marcono1234 commented Dec 27, 2021

Thank you! It looks like the additional JSON properties, such as leftValidDays, mixSuccess or notifyMessage, are obtained by Fastjson from the getter methods of the class (for example getLeftValidDays()), but there are no corresponding fields for them. Gson unfortunately does not support getter methods, it only support fields, see #232.

@meijieman
Copy link
Author

i see now. its not a normal model classes.
thanks~

@eamonnmcmanus
Copy link
Member

It looks as if the problem here is as described above, namely that Gson currently doesn't support getter methods. Since that's covered by #232, I'm going to close this, but feel free to reopen if needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants