Gson 试图解析带有 @Expose(false) 注释的字段并崩溃
Posted
技术标签:
【中文标题】Gson 试图解析带有 @Expose(false) 注释的字段并崩溃【英文标题】:Gson trying to parse fields annotated with @Expose(false) and crashing 【发布时间】:2018-12-23 10:15:23 【问题描述】:我正在尝试使用 Gson 将一个非常基本的对象序列化为 JSON。
这是课程
@org.greenrobot.greendao.annotation.Entity
public class Giveaway
@Id(autoincrement = true)
@Expose(serialize = false,deserialize = false)
private Long id;
@NotNull
private String owner;
private Date raffleDate;
private String thumbnailUrl;
@ToMany(referencedJoinProperty = "giveawayId")
private List<Influencer> mustFollowList;
@NotNull
@Convert(converter = GiveawayCommentTypeConverter.class, columnType = Integer.class)
private GiveawayCommentType tipo;
private String specifWordValue;
private Integer amountFriendsToIndicate;
@NotNull
@Unique
private String mediaId;
//to reflect the relationships
@ToMany(referencedJoinProperty = "raffle")
@Expose(deserialize = false, serialize = false)
private List<UserOnGiveaway> attendantsTickets;
如您所见,我有 2 个字段我不想被序列化,所以我用 expose = false
注释它们,但即使使用这个 Gson 试图序列化它们并由于 OutOfMemory
而崩溃。 (UserOnGiveaway 对 Giveaway 有一个循环引用,这解释了它崩溃的原因。)
Gson 代码是:
Gson parser = new GsonBuilder().setPrettyPrinting().excludeFieldsWithModifiers(Modifier.FINAL, Modifier.STATIC, Modifier.TRANSIENT).create();
StringBuilder sb = new StringBuilder(200);
try
for (Giveaway g : this.dao.getGiveawayDao().loadAll())
sb.append(parser.toJson(g) + "\n");
catch (Exception e)
e.printStackTrace();
我不想使用.excludeFieldsWithoutExposeAnnotation()
,因为它迫使我编写不必要的内容并注释所有内容以排除 1 个字段...
我做错了什么?
【问题讨论】:
【参考方案1】:在您的 attendantsTickets
字段上使用 transient
Java 关键字,不要在您的情况下使用 @Expose
。
来自文档https://github.com/google/gson/blob/master/UserGuide.md: “如果一个字段被标记为瞬态,(默认情况下)它会被忽略并且不包含在 JSON 序列化或反序列化中。”
private transient List<UserOnGiveaway> attendantsTickets;
还可以查看这个 Gson 配置选项:GsonBuilder.excludeFieldsWithModifiers(int... modifiers)
更多关于transient
在java中的信息你可以在这里阅读https://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.3.1.3
如果您的代码依赖于瞬态行为,例如 JPA 或其他数据映射工具,您将不得不使用 Gson 排除策略。
您可以像这样创建注释并用它标记应该受自定义序列化影响的字段,然后在排除策略代码中使用它:
@Target(value = ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface ExcludeFromJson
.........
void gson()
new GsonBuilder().setExclusionStrategies(new ExclusionStrategy()
@Override
boolean shouldSkipField(FieldAttributes f)
return f.getAnnotation(ExcludeFromJson.class) != null;
@Override
boolean shouldSkipClass(Class<?> clazz)
return false;
)
..........
@ExcludeFromJson
private transient List<UserOnGiveaway> attendantsTickets;
【讨论】:
它不起作用,因为它是一个域对象,我需要持久化它,用瞬态标记它们会使我的持久性框架忽略它们 好的,那么你需要使用自定义排除策略。您可以创建注释并用它标记要排除的字段,将代码添加到我的答案中,见上文。 这可能会起作用,但我仍然不喜欢这种方法,如果我明确告诉它不要这样做,为什么 gson 会试图解析某些东西......无论如何,如果我需要自己制作@987654331 @我不需要创建一个新的注释,我可以简单地使用Gson
选择忽略的那个
@RafaelLima 我不知道为什么 Gson 开发人员决定实施 Expose 策略,而不是实施类似 Hide 策略的东西。如果你愿意,你可以尝试切换到 Jackson,它有不同的方法来管理排除/包含策略***.com/questions/13764280/…【参考方案2】:
excludeFieldsWithModifiers(Modifier.FINAL, Modifier.STATIC, Modifier.TRANSIENT)
它说明如果任何变量被声明为最终、静态或瞬态,则不会被序列化(和反序列化)。 所以,而不是@Expose 注释
@Expose(deserialize = false, serialize = false)
使用上述三个关键字中的任何一个,即:
private transient Long id;
【讨论】:
持久化是什么意思?以上是关于Gson 试图解析带有 @Expose(false) 注释的字段并崩溃的主要内容,如果未能解决你的问题,请参考以下文章
gson的 Expose注解和 SerializedName注解
“无法解析的日期:1302828677828”试图用 Gson 反序列化从服务器接收到的毫秒格式日期