我正在尝试将json文档中的一个简单的字符串元素数组转换为java List,它位于使用genson的bean中。我原以为这会自动发生,但它不起作用。我错过了什么吗?
这是我的Json-String:
{"id":12345,"permissions":["READ_XX","WRITE_XX"]}
这是我的对象的输出,显示我的权限列表没有填充:
DefaultRole [id=12345, name=null, permissions=[]]
我的DefaultRole类看起来像这样:
public class DefaultRole implements Role
{
public Id id = null;
@XmlElementWrapper(name = "permissions")
@XmlElement(name = "permission")
private List<String> permissions = Lists.newArrayList();
@Inject
public DefaultRole()
{
}
[...]
JAXB注释仅用于XML转换。他们不应该在这里发挥作用。
我正在创建像这样的Genson对象:
Genson genson = new Genson.Builder()
.setWithClassMetadata(false)
.setWithBeanViewConverter(true)
.setWithDebugInfoPropertyNameResolver(true)
.setSkipNull(true)
.create();
我的反序列化调用:
genson().deserialize(jsonString, DefaultRole.class)
有没有人知道如何将我的json字符串数组用于存放在bean中的java List对象?
我现在更进了一步。我回到了根,然后开始使用一个只有字符串列表的基本bean。正如预期的那样,第一次,这是有效的。前一个对象之间的区别主要是这个跟随bean规范。另一个对象(DefaultRole)遵循fluid-object-pattern(不确定这是否是正确的denfinition)。基本上,不是setter方法是void,而是返回对象,以便可以很容易地以流畅的方式设置下一个值。
这样可行:
public void setPermissions(List<String> permissions)
{
this.permissions = permissions;
}
这不起作用:
public Role setPermissions(List<String> permissions)
{
this.permissions = permissions;
return this;
}
还有其他人遇到过这个问题吗?有什么方法可以切换所有我的bean来遵守bean规范?是使用纯字段级别而不是通过setter方法的唯一选择吗?
嗨,我不确定如何回答需要帮助了解我所做的代码的问题。
无论如何,非常感谢你的帮助。我真的很喜欢第三个选项,这是我正在寻找的东西。不幸的是,我现在收到错误“找不到类型类xxx.DefaultRole的构造函数”。根据你在答案中所说的,当返回Trilean.UNKNOWN时,不应该这样,因为搜索会继续。
我将以下代码添加到我的genson-builder中:
.set(new BeanMutatorAccessorResolver.BaseResolver()
{
@Override
public Trilean isMutator(Method method, Class<?> fromClass)
{
if (Reflect.isSetter(method))
return Trilean.TRUE;
else
return Trilean.UNKNOWN;
}
})
我的Reflect.isSetter(方法)看起来像这样(代码改编自这里:http://www.asgteach.com/blog/?p=559):
public static boolean isSetter(Method method)
{
return Modifier.isPublic(method.getModifiers()) &&
(method.getReturnType().equals(void.class) || method.getReturnType().equals(method.getDeclaringClass())) &&
method.getParameterTypes().length == 1 &&
method.getName().matches("^set[A-Z].*");
}
BaseResolver为尚未实现的所有内容返回Trilean.UNKNOWN。因此它应该使用标准逻辑找到构造函数,如果不是?
为了完整起见,我将发布实际有效的代码:
public static final Genson genson()
{
Genson genson = new Genson.Builder()
.setSkipNull(true)
.setWithClassMetadata(false)
.setWithDebugInfoPropertyNameResolver(true)
.setWithBeanViewConverter(true)
.with(new BeanMutatorAccessorResolver.BaseResolver()
{
@Override
public Trilean isMutator(Method method, Class<?> fromClass)
{
if (Reflect.isSetter(method))
return Trilean.TRUE;
else
return Trilean.UNKNOWN;
}
})
.create();
return genson;
}
这里需要注意的是,“。set(new BeanMutatorAccessorResolver.BaseResolver()”必须替换为“.with(new BeanMutatorAccessorResolver.BaseResolver()”(注意“with”而不是“set”)。这很重要,因为标准的解析器不再使用,否则你最终会得到我所遇到的错误,无法再找到构造函数。
isSetter方法如下所示:
public static boolean isSetter(Method method)
{
return Modifier.isPublic(method.getModifiers())
&& (method.getReturnType().equals(void.class) || method.getReturnType().isAssignableFrom(method.getDeclaringClass()))
&& method.getParameterTypes().length == 1
&& method.getName().matches("^set[A-Z].*");
}
这里需要注意的是,在将return-type与声明类进行比较时,我最初使用的是“equals”而不是“isAssignableFrom”。这仅在返回类型与声明它的类完全相同时才有效。当使用接口作为返回值时,它不再起作用。通过使用“method.getReturnType()。isAssignableFrom(method.getDeclaringClass())”而不是这也适用于接口(包括超级接口)。
谢谢, 迈克尔
答案 0 :(得分:0)
事实上,Genson(与大多数其他lib一样)使用Java bean约定来检测setter / getter,因此它不会将setPermissions检测为setter。
两个快速解决方案:
1)您可以使用@JsonProperty对其进行注释(无需定义名称)。这将告诉genson将它用作setter(但是genson不会重用返回的对象,这意味着在你的情况下它可以工作,但像这样的构建器就像那样坚固)。
2)你可以强制genson只使用字段而不使用方法(这直接设置字段值而不调用get / set)。
Genson.Builder()
.setUseFields(true)
.setFieldFilter(VisibilityFilter.DEFAULT)
.setUseGettersAndSetters(false)
.create();
更通用:
3)在链中添加一个自定义BeanMutatorAccessorResolver,它将处理您的特定情况
Genson genson = Genson.Builder().with(new BeanMutatorAccessorResolver.BaseResolver() {
@Override
public Trilean isMutator(Method method, Class<?> fromClass) {
// if method starts with setXXX and return type same as method.getDeclaringClass
return Trilean.TRUE;
// else return Tilean.UNKNOWN genson will use its built-in resolvers
}
}).create();
修改强>
应该已经看到您在构建器上使用 set 而不是 with 方法。当您在genson API中看到setXXX时,这通常意味着您将覆盖/强制某种机制(您设置一个值),但用于添加行为。