gpt4 book ai didi

java - 使用 genson 将 json 字符串反序列化为流体对象

转载 作者:行者123 更新时间:2023-11-29 08:52:36 24 4
gpt4 key购买 nike

我正在尝试将 json 文档中的简单字符串元素数组转换为 java List,它位于使用 genson 的 bean 中。我期待这会自动发生,但它不起作用。我错过了什么吗?

这是我的 Json 字符串:

{"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) 遵循流体对象模式(不确定这是否是正确的定义)。基本上,我返回对象而不是 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(method) 看起来像这样(代码改编自这里: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].*");
}

这里重要的是要注意,在将返回类型与声明类进行比较时,我最初使用的是“equals”而不是“isAssignableFrom”。这仅在返回类型与其声明的类完全相同时才有效。当使用接口(interface)作为返回值时,它不再有效。通过使用“method.getReturnType().isAssignableFrom(method.getDeclaringClass())”,这也适用于接口(interface)(包括 super 接口(interface))。

谢谢,迈克尔

最佳答案

事实上,Genson(与大多数其他库一样)使用 Java bean 约定来检测 setter/getter,因此它不会将您的 setPermissions 检测为 setter。

两个快速解决方案:

1)可以用@JsonProperty注解(不需要定义名字)。这将告诉 genson 将它用作 setter(但是 genson 不会重用返回的对象,这意味着在您的情况下它可以工作,但像这样的构建器是 nut 支持的)。

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 时,这通常意味着您将覆盖/强制执行某些机制(您设置一个值),但 with 用于添加行为。

关于java - 使用 genson 将 json 字符串反序列化为流体对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21956950/

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