gpt4 book ai didi

json - 如何配置 Gson 以序列化一组 JSR-303 ConstraintViolation 对象?

转载 作者:行者123 更新时间:2023-12-03 22:48:29 29 4
gpt4 key购买 nike

我似乎无法找到如何使用 Gson 序列化 Hibernate 的约束违规实现。

这是我到目前为止所尝试的。

方法一

MyPojo aPojo = new MyPojo();
Gson gson = new Gson();
Set<ConstraintViolation<MyPojo>> violations = validator.validate(aPojo);
System.out.println(gson.toJson(violations));

失败并出现此错误:
java.lang.UnsupportedOperationException: 
Attempted to serialize java.lang.Class: com.bar.baz.MyPojo.
Forgot to register a type adapter?
at com.google.gson.internal.bind.TypeAdapters$1.write(TypeAdapters.java:67)
at com.google.gson.internal.bind.TypeAdapters$1.write(TypeAdapters.java:61)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
at com.google.gson.internal.bind.ObjectTypeAdapter.write(ObjectTypeAdapter.java:107)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:96)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:60)
at com.google.gson.Gson.toJson(Gson.java:593)
at com.google.gson.Gson.toJson(Gson.java:572)
at com.google.gson.Gson.toJson(Gson.java:527)
at com.google.gson.Gson.toJson(Gson.java:507)

方法二
Gson gson = new Gson();
Set<ConstraintViolation<MyPojo>> violations = validator.validate(MyPojo);

System.out.println(
gson.toJson(violations,
new TypeToken<ConstraintViolation<MyPojo>>() {}.getType())
);

由于未序列化 MyPojo 的属性而失败:

输出: {} .

方法 3

我期待这种方法将序列化委托(delegate)给我的自定义序列化器,但它仍然失败:
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(
new TypeToken<ConstraintViolation<MyPojo>>() {}.getType(),
new JsonSerializer<ConstraintViolation<MyPojo>>() {
@Override
public JsonElement serialize(ConstraintViolation<MyPojo> src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject result = new JsonObject();

result.addProperty("aTestProperty", "A Test Value");

return result;
}

});

Gson gson = builder.create();

Set<ConstraintViolation<MyPojo>> violations = validator.validate(MyPojo);
System.out.println(gson.toJson(violations));

但是它失败并出现此错误:
java.lang.UnsupportedOperationException: 
Attempted to serialize java.lang.Class:
com.bar.baz.MyPojo.
Forgot to register a type adapter?
at com.google.gson.internal.bind.TypeAdapters$1.write(TypeAdapters.java:67)
at com.google.gson.internal.bind.TypeAdapters$1.write(TypeAdapters.java:61)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)
at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)
at com.google.gson.internal.bind.ObjectTypeAdapter.write(ObjectTypeAdapter.java:107)
at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:96)
at com.google.gson.internal.bind.CollectionTypeAdapterFactory$Adapter.write(CollectionTypeAdapterFactory.java:60)
at com.google.gson.Gson.toJson(Gson.java:593)
at com.google.gson.Gson.toJson(Gson.java:572)
at com.google.gson.Gson.toJson(Gson.java:527)
at com.google.gson.Gson.toJson(Gson.java:507)

方法 4

查看错误消息,我认为这可能有效:
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(
new TypeToken<ConstraintViolation<MyPojo>>() {}.getType(),
new JsonSerializer<ConstraintViolation<MyPojo>>() {
@Override
public JsonElement serialize(ConstraintViolation<MyPojo> src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject result = new JsonObject();

result.addProperty("aTestProperty", "A Test Value");

return result;
}

});

builder.registerTypeAdapter(
new TypeToken<MyPojo>() {}.getType(),
new JsonSerializer<MyPojo>() {
@Override
public JsonElement serialize(MyPojo src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject result = new JsonObject();

result.addProperty("anotherTestProperty", "Another Test Value");

return result;
}

});

Gson gson = builder.create();

Set<ConstraintViolation<MyPojo>> violations = validator.validate(MyPojo);
System.out.println(gson.toJson(violations));

但它失败并出现类似的错误。

方法 5:工作但丑陋

我设法做的唯一一件事是使用 ConstraintViolation 的供应商(Hibernate)特定实现的类型注册序列化程序:
Set<ConstraintViolation<MyPojo>> violations = validator.validate(MyPojo);

GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(
new TypeToken<ConstraintViolationImpl>() {}.getType(),
new JsonSerializer<ConstraintViolation<MyPojo>>() {
@Override
public JsonElement serialize(ConstraintViolation<MyPojo> src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject result = new JsonObject();

result.addProperty("aTestProperty", "A Test Value");

return result;
}

});

Gson gson = builder.create();
System.out.println(gson.toJson(violations));

有没有办法在不依赖 ConstraintViolation 的具体实现的情况下完成这项工作? (即 org.hibernate.validator.internal.engine.ConstraintViolationImpl )?

最佳答案

似乎没有合理的方法来序列化 javax.validation.ConstraintViolation对象。事实上,即使是 Jackson 在尝试序列化集合时也会出错:

Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: fromIndex(0) > toIndex(-1) (through reference chain: java.util.HashSet[0]->org.hibernate.validator.internal.engine.ConstraintViolationImpl["propertyPath"]->org.hibernate.validator.internal.engine.path.PathImpl["pathWithoutLeafNode"]->org.hibernate.validator.internal.engine.path.PathImpl["pathWithoutLeafNode"]->org.hibernate.validator.internal.engine.path.PathImpl["pathWithoutLeafNode"])
at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:232)

目前,我只是将这组错误转换为我编写的一组自定义 POJO 并将其序列化。

自定义验证错误 POJO:
public class ValidationError {

private String className;
private String propertyPath;
private String errorMessage;

public static Set<ValidationError> fromViolations(Set violations) {
Set<ValidationError> errors = new HashSet<ValidationError>();

for (Object o : violations) {
ConstraintViolation v = (ConstraintViolation) o;

ValidationError error = new ValidationError();
error.setClassName(v.getRootBeanClass().getSimpleName());
error.setErrorMessage(v.getMessage());
error.setPropertyPath(v.getPropertyPath().toString());
errors.add(error);
}

return errors;
}

public String getClassName() {
return className;
}

public void setClassName(String className) {
this.className = className;
}

public String getPropertyPath() {
return propertyPath;
}

public void setPropertyPath(String propertyPath) {
this.propertyPath = propertyPath;
}

public String getErrorMessage() {
return errorMessage;
}

public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}

@Override
public String toString() {
return "ValidationError{" +
"className='" + className + '\'' +
", propertyPath='" + propertyPath + '\'' +
", errorMessage='" + errorMessage + '\'' +
'}';
}
}

示例用法:
Set<ConstraintViolation<MyBean>> violations = validator.validate(myBean);
Set<ValidationError> errors = ValidationError.fromViolations(violations);

GsonBuilder gsonBuilder = new GsonBuilder();
Gson gson = gsonBuilder.create();
System.out.println(gson.toJson(errors));

更新

为了记录起见,值得一提的是,XStream 可以像魅力一样序列化违反约束的集合:
XStream xstream = new XStream(new JettisonMappedXmlDriver());
xstream.setMode(XStream.NO_REFERENCES);
System.out.println(xstream.toXML(violations));

然而,生成的对象图过于冗长,无论如何都不适合在生产中使用。您可以看到示例输出 here .

关于json - 如何配置 Gson 以序列化一组 JSR-303 ConstraintViolation 对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21926337/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com