Liv*_* T. 404 java serialization json gson
我正在努力学习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;
}
Run Code Online (Sandbox Code Playgroud)
我可以使用GsonBuilder并添加ExclusionStrategy像一个字段名称firstName或country,但我似乎无法管理排除像某些领域的性能country.name.
使用该方法public boolean shouldSkipField(FieldAttributes fa),FieldAttributes不包含足够的信息来匹配具有过滤器的字段country.name.
对于这个问题的解决方案,我将不胜感激.
PS:我想避免注释,因为我想对此进行改进并使用RegEx来过滤字段.
谢谢
编辑:我试图看看是否可以模拟Struts2 JSON插件的行为
使用Gson
<interceptor-ref name="json">
<param name="enableSMD">true</param>
<param name="excludeProperties">
login.password,
studentList.*\.sin
</param>
</interceptor-ref>
Run Code Online (Sandbox Code Playgroud)
编辑: 我重新打开了以下添加的问题:
我添加了第二个相同类型的字段,以进一步澄清这个问题.基本上我想排除country.name但不是countrOfBirth.name.我也不想将Country排除在类型之外.所以类型是相同的,它是我想要精确定位和排除的对象图中的实际位置.
Chr*_*ine 615
您不希望序列化的任何字段都应该使用"transient"修饰符,这也适用于json序列化程序(至少它适用于我使用过的一些,包括gson).
如果你不希望名字显示在序列化的json中,给它一个transient关键字,例如:
private transient String name;
Run Code Online (Sandbox Code Playgroud)
Jay*_*Pea 312
Nishant提供了一个很好的解决方案,但有一种更简单的方法.只需使用@Expose注释标记所需的字段,例如:
@Expose private Long id;
Run Code Online (Sandbox Code Playgroud)
省去您不想序列化的任何字段.然后以这种方式创建您的Gson对象:
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
Run Code Online (Sandbox Code Playgroud)
Nis*_*ant 228
所以,你要排除 firstName和country.name.这是你ExclusionStrategy应该看起来的样子
public class TestExclStrat implements ExclusionStrategy {
public boolean shouldSkipClass(Class<?> arg0) {
return false;
}
public boolean shouldSkipField(FieldAttributes f) {
return (f.getDeclaringClass() == Student.class && f.getName().equals("firstName"))||
(f.getDeclaringClass() == Country.class && f.getName().equals("name"));
}
}
Run Code Online (Sandbox Code Playgroud)
如果你仔细看它返回true的Student.firstName和Country.name,这是要排除的东西.
你需要ExclusionStrategy像这样应用这个,
Gson gson = new GsonBuilder()
.setExclusionStrategies(new TestExclStrat())
//.serializeNulls() <-- uncomment to serialize NULL fields as well
.create();
Student src = new Student();
String json = gson.toJson(src);
System.out.println(json);
Run Code Online (Sandbox Code Playgroud)
返回:
{ "中间名": "J", "缩写": "PF", "姓氏": "油炸", "国家":{ "ID":91}}
我假设country对象id = 91L在学生班中初始化.
你可能会喜欢.例如,您不希望序列化名称中包含"name"字符串的任何字段.做这个:
{ "middleName": "J.", "initials": "P.F", "lastName": "Fry", "country": { "id": 91}}
Run Code Online (Sandbox Code Playgroud)
这将返回:
public boolean shouldSkipField(FieldAttributes f) {
return f.getName().toLowerCase().contains("name");
}
Run Code Online (Sandbox Code Playgroud)
编辑:根据要求添加了更多信息.
这样ExclusionStrategy做,但你需要通过"完全合格的字段名称".见下文:
{ "initials": "P.F", "country": { "id": 91 }}
Run Code Online (Sandbox Code Playgroud)
以下是我们如何一般地使用它.
public class TestExclStrat implements ExclusionStrategy {
private Class<?> c;
private String fieldName;
public TestExclStrat(String fqfn) throws SecurityException, NoSuchFieldException, ClassNotFoundException
{
this.c = Class.forName(fqfn.substring(0, fqfn.lastIndexOf(".")));
this.fieldName = fqfn.substring(fqfn.lastIndexOf(".")+1);
}
public boolean shouldSkipClass(Class<?> arg0) {
return false;
}
public boolean shouldSkipField(FieldAttributes f) {
return (f.getDeclaringClass() == c && f.getName().equals(fieldName));
}
}
Run Code Online (Sandbox Code Playgroud)
它返回:
Gson gson = new GsonBuilder()
.setExclusionStrategies(new TestExclStrat("in.naishe.test.Country.name"))
//.serializeNulls()
.create();
Student src = new Student();
String json = gson.toJson(src);
System.out.println(json);
Run Code Online (Sandbox Code Playgroud)
pkk*_*pkk 213
在阅读了我发现的所有可用答案之后,在我的情况下,最灵活的是使用自定义@Exclude注释.所以,我为此实现了简单的策略(我不想标记所有字段,@Expose也不想使用transient与应用程序Serializable序列化相冲突的字段):
注解:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Exclude {
}
Run Code Online (Sandbox Code Playgroud)
战略:
public class AnnotationExclusionStrategy implements ExclusionStrategy {
@Override
public boolean shouldSkipField(FieldAttributes f) {
return f.getAnnotation(Exclude.class) != null;
}
@Override
public boolean shouldSkipClass(Class<?> clazz) {
return false;
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
new GsonBuilder().setExclusionStrategies(new AnnotationExclusionStrategy()).create();
Run Code Online (Sandbox Code Playgroud)
Der*_*key 78
我遇到了这个问题,其中我只想从序列化中排除少量字段,因此我开发了一个相当简单的解决方案,它使用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();
Run Code Online (Sandbox Code Playgroud)
现在我可以轻松地使用@Expose(serialize = false)或@Expose(deserialize = false)注释排除一些字段(请注意,两个@Expose属性的默认值都是true).您当然可以使用@Expose(serialize = false, deserialize = false),但通过声明字段transient(这仍然适用于这些自定义排除策略)可以更简洁地完成.
小智 18
你可以用gson探索json树.
尝试这样的事情:
gson.toJsonTree(student).getAsJsonObject()
.get("country").getAsJsonObject().remove("name");
Run Code Online (Sandbox Code Playgroud)
您还可以添加一些属性:
gson.toJsonTree(student).getAsJsonObject().addProperty("isGoodStudent", false);
Run Code Online (Sandbox Code Playgroud)
用gson 2.2.4测试.
Dom*_* D. 16
我想出了一个类工厂来支持这个功能.传递要排除的字段或类的任意组合.
public class GsonFactory {
public static Gson build(final List<String> fieldExclusions, final List<Class<?>> classExclusions) {
GsonBuilder b = new GsonBuilder();
b.addSerializationExclusionStrategy(new ExclusionStrategy() {
@Override
public boolean shouldSkipField(FieldAttributes f) {
return fieldExclusions == null ? false : fieldExclusions.contains(f.getName());
}
@Override
public boolean shouldSkipClass(Class<?> clazz) {
return classExclusions == null ? false : classExclusions.contains(clazz);
}
});
return b.create();
}
}
Run Code Online (Sandbox Code Playgroud)
要使用,请创建两个列表(每个都是可选的),然后创建您的GSON对象:
static {
List<String> fieldExclusions = new ArrayList<String>();
fieldExclusions.add("id");
fieldExclusions.add("provider");
fieldExclusions.add("products");
List<Class<?>> classExclusions = new ArrayList<Class<?>>();
classExclusions.add(Product.class);
GSON = GsonFactory.build(null, classExclusions);
}
private static final Gson GSON;
public String getSomeJson(){
List<Provider> list = getEntitiesFromDatabase();
return GSON.toJson(list);
}
Run Code Online (Sandbox Code Playgroud)
Hib*_*bem 13
我用自定义注释解决了这个问题.这是我的"SkipSerialisation"注释类:
@Target (ElementType.FIELD)
public @interface SkipSerialisation {
}
Run Code Online (Sandbox Code Playgroud)
这是我的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;
}
});
Run Code Online (Sandbox Code Playgroud)
示例:
public class User implements Serializable {
public String firstName;
public String lastName;
@SkipSerialisation
public String email;
}
Run Code Online (Sandbox Code Playgroud)
loo*_*shc 10
Kotlin 的@Transient注释显然也起到了作用。
data class Json(
@field:SerializedName("serialized_field_1") val field1: String,
@field:SerializedName("serialized_field_2") val field2: String,
@Transient val field3: String
)
Run Code Online (Sandbox Code Playgroud)
输出:
{"serialized_field_1":"VALUE1","serialized_field_2":"VALUE2"}
Run Code Online (Sandbox Code Playgroud)
或者可以说什么字段不会暴露:
Gson gson = gsonBuilder.excludeFieldsWithModifiers(Modifier.TRANSIENT).create();
Run Code Online (Sandbox Code Playgroud)
你的班级属性:
private **transient** boolean nameAttribute;
Run Code Online (Sandbox Code Playgroud)
小智 8
我使用了这个策略:我排除了没有用@SerializedName注释标记的每个字段,即:
public class Dummy {
@SerializedName("VisibleValue")
final String visibleValue;
final String hiddenValue;
public Dummy(String visibleValue, String hiddenValue) {
this.visibleValue = visibleValue;
this.hiddenValue = hiddenValue;
}
}
public class SerializedNameOnlyStrategy implements ExclusionStrategy {
@Override
public boolean shouldSkipField(FieldAttributes f) {
return f.getAnnotation(SerializedName.class) == null;
}
@Override
public boolean shouldSkipClass(Class<?> clazz) {
return false;
}
}
Gson gson = new GsonBuilder()
.setExclusionStrategies(new SerializedNameOnlyStrategy())
.create();
Dummy dummy = new Dummy("I will see this","I will not see this");
String json = gson.toJson(dummy);
Run Code Online (Sandbox Code Playgroud)
它回来了
{"VisibleValue":"我会看到这个"}
另一种方法(如果您需要决定在运行时排除字段,尤其有用)是使用您的gson实例注册TypeAdapter.示例如下:
Gson gson = new GsonBuilder()
.registerTypeAdapter(BloodPressurePost.class, new BloodPressurePostSerializer())
Run Code Online (Sandbox Code Playgroud)
在下面的情况中,服务器会期望两个值中的一个,但由于它们都是int,因此gson会将它们都序列化.我的目标是从发布到服务器的json中省略任何零(或更少)的值.
public class BloodPressurePostSerializer implements JsonSerializer<BloodPressurePost> {
@Override
public JsonElement serialize(BloodPressurePost src, Type typeOfSrc, JsonSerializationContext context) {
final JsonObject jsonObject = new JsonObject();
if (src.systolic > 0) {
jsonObject.addProperty("systolic", src.systolic);
}
if (src.diastolic > 0) {
jsonObject.addProperty("diastolic", src.diastolic);
}
jsonObject.addProperty("units", src.units);
return jsonObject;
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
306506 次 |
| 最近记录: |