我在努力学习Gson,我在与场排除作斗争。这是我的课程
public class Student {
private Long id;
private String firstName = "Philip";
private String middleName = "J.";
private String initials = "P.F";
private String lastName = "Fry";
private Country country;
private Country countryOfBirth;
}
public class Country {
private Long id;
private String name;
private Object other;
}
我可以使用GsonBuilder,并为字段名如firstName或country添加一个ExclusionStrategy,但我似乎无法排除某些字段的属性,如country.name。
使用方法public boolean shouldSkipField(FieldAttributes fa), FieldAttributes不包含足够的信息来匹配像country.name这样的过滤器。
附注:我想避免使用注释,因为我想改进这一点,并使用RegEx过滤字段。
编辑:我试着看看是否有可能模拟Struts2 JSON插件的行为
使用Gson
<interceptor-ref name="json">
<param name="enableSMD">true</param>
<param name="excludeProperties">
login.password,
studentList.*\.sin
</param>
</interceptor-ref>
编辑:
我重新提出这个问题,补充如下:
我添加了第二个具有相同类型的字段,以进一步澄清这个问题。基本上我想要排除country。name而不是countrofbirth。name。我也不想把Country排除在外。
所以类型是一样的我想要精确定位和排除的对象图中的实际位置。
这是我经常使用的:
Gson中实现的默认行为是忽略空对象字段。
表示Gson对象不将空值字段序列化为JSON。如果Java对象中的字段为空,Gson将排除它。
您可以使用此函数将某些对象转换为null或由您自己设置的良好值
/**
* convert object to json
*/
public String toJson(Object obj) {
// Convert emtpy string and objects to null so we don't serialze them
setEmtpyStringsAndObjectsToNull(obj);
return gson.toJson(obj);
}
/**
* Sets all empty strings and objects (all fields null) including sets to null.
*
* @param obj any object
*/
public void setEmtpyStringsAndObjectsToNull(Object obj) {
for (Field field : obj.getClass().getDeclaredFields()) {
field.setAccessible(true);
try {
Object fieldObj = field.get(obj);
if (fieldObj != null) {
Class fieldType = field.getType();
if (fieldType.isAssignableFrom(String.class)) {
if(fieldObj.equals("")) {
field.set(obj, null);
}
} else if (fieldType.isAssignableFrom(Set.class)) {
for (Object item : (Set) fieldObj) {
setEmtpyStringsAndObjectsToNull(item);
}
boolean setFielToNull = true;
for (Object item : (Set) field.get(obj)) {
if(item != null) {
setFielToNull = false;
break;
}
}
if(setFielToNull) {
setFieldToNull(obj, field);
}
} else if (!isPrimitiveOrWrapper(fieldType)) {
setEmtpyStringsAndObjectsToNull(fieldObj);
boolean setFielToNull = true;
for (Field f : fieldObj.getClass().getDeclaredFields()) {
f.setAccessible(true);
if(f.get(fieldObj) != null) {
setFielToNull = false;
break;
}
}
if(setFielToNull) {
setFieldToNull(obj, field);
}
}
}
} catch (IllegalAccessException e) {
System.err.println("Error while setting empty string or object to null: " + e.getMessage());
}
}
}
private void setFieldToNull(Object obj, Field field) throws IllegalAccessException {
if(!Modifier.isFinal(field.getModifiers())) {
field.set(obj, null);
}
}
private boolean isPrimitiveOrWrapper(Class fieldType) {
return fieldType.isPrimitive()
|| fieldType.isAssignableFrom(Integer.class)
|| fieldType.isAssignableFrom(Boolean.class)
|| fieldType.isAssignableFrom(Byte.class)
|| fieldType.isAssignableFrom(Character.class)
|| fieldType.isAssignableFrom(Float.class)
|| fieldType.isAssignableFrom(Long.class)
|| fieldType.isAssignableFrom(Double.class)
|| fieldType.isAssignableFrom(Short.class);
}
我遇到了这个问题,在这个问题中,我只想从序列化中排除少量字段,所以我开发了一个相当简单的解决方案,使用带有自定义排除策略的Gson的@Expose注释。
使用@Expose的唯一内置方法是设置GsonBuilder.excludeFieldsWithoutExposeAnnotation(),但正如名称所示,没有显式@Expose的字段将被忽略。由于我只有几个想要排除的字段,我发现将注释添加到每个字段非常麻烦。
实际上,我想要的是相反的,其中所有内容都包括在内,除非我显式地使用@Expose来排除它。我使用了以下排除策略来实现这一点:
new GsonBuilder()
.addSerializationExclusionStrategy(new ExclusionStrategy() {
@Override
public boolean shouldSkipField(FieldAttributes fieldAttributes) {
final Expose expose = fieldAttributes.getAnnotation(Expose.class);
return expose != null && !expose.serialize();
}
@Override
public boolean shouldSkipClass(Class<?> aClass) {
return false;
}
})
.addDeserializationExclusionStrategy(new ExclusionStrategy() {
@Override
public boolean shouldSkipField(FieldAttributes fieldAttributes) {
final Expose expose = fieldAttributes.getAnnotation(Expose.class);
return expose != null && !expose.deserialize();
}
@Override
public boolean shouldSkipClass(Class<?> aClass) {
return false;
}
})
.create();
现在,我可以很容易地用@Expose(serialize = false)或@Expose(deserialize = false)注释排除一些字段(注意,这两个@Expose属性的默认值都是true)。当然,您可以使用@Expose(serialize = false, deserialize = false),但是通过声明字段transient(使用这些自定义排除策略仍然有效)可以更简洁地实现这一点。
我用自定义注释解决了这个问题。
这是我的“SkipSerialisation”注释类:
@Target (ElementType.FIELD)
public @interface SkipSerialisation {
}
这是我的GsonBuilder:
gsonBuilder.addSerializationExclusionStrategy(new ExclusionStrategy() {
@Override public boolean shouldSkipField (FieldAttributes f) {
return f.getAnnotation(SkipSerialisation.class) != null;
}
@Override public boolean shouldSkipClass (Class<?> clazz) {
return false;
}
});
例子:
public class User implements Serializable {
public String firstName;
public String lastName;
@SkipSerialisation
public String email;
}