我有一个JSON结构,其中包含字符串到对象的映射:
{
"domains": {
"ldap": {
"users": {
"fwalther": {
"firstName": "Fritz",
"lastName": "Walther"
},
// ...
}
}
},
// ...
}
我希望使用Jackson将此结构反序列化为域
和用户
对象,并且我希望每个用户都有一个对其映射键(即用户ID)和域
容器的反向引用。这两种方法都有效,但如果我试图同时获取两个引用,则会失败。
Java带有@JsonManaged参考
和@JsonBack参考
的类:
public class Domain {
@JsonManagedReference
@JsonDeserialize(contentUsing = UserDeserializer.class)
private Map<String, User> users;
public Map<String, User> getUsers() {
return users;
}
}
public class User {
@JsonBackReference
private Domain domain;
String userId;
private String firstName;
private String lastName;
// ... getters
}
获取映射键的自定义反序列化程序:
public class UserDeserializer extends JsonDeserializer<User> {
@Override
public User deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
String key = p.getCurrentName();
User result = p.readValueAs(User.class);
result.userId = key;
return result;
}
}
这两种机制,即@JsonManagedReference
/@JsonBackReference
对和@JsonDeserialize
与自定义反序列化器,如果我只激活其中一个,它们都可以工作。但是如果我结合这些机制(如上面的代码所示),在解析JSON时会出现以下异常:
java.lang.IllegalArgumentException: Cannot handle managed/back reference 'defaultReference': type: value deserializer of type org.example.UserDeserializer does not support them
at com.fasterxml.jackson.databind.JsonDeserializer.findBackReference(JsonDeserializer.java:366) ~[jackson-databind-2.9.8.jar:2.9.8]
at com.fasterxml.jackson.databind.deser.std.ContainerDeserializerBase.findBackReference(ContainerDeserializerBase.java:104) ~[jackson-databind-2.9.8.jar:2.9.8]
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase._resolveManagedReferenceProperty(BeanDeserializerBase.java:786) ~[jackson-databind-2.9.8.jar:2.9.8]
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.resolve(BeanDeserializerBase.java:487) ~[jackson-databind-2.9.8.jar:2.9.8]
...
查看引发异常的代码,我发现我需要在自定义反序列化程序中实现findBackReference
,但我不知道如何实现,也找不到相关信息。有什么想法吗?
或者有其他方法来获取映射键和包含对象的返回引用?
在这个答案的帮助下,我找到了解决方案:自定义反序列化器需要基于默认的反序列化器,它正确地实现了反向引用机制。
这比仅仅从正确的基类继承要复杂一些。相反,您需要通过自定义的beandSerializerModifier
获得(完全配置的)默认反序列化程序实例,然后将此实例传递给DelegatingDeserializer
的子类:
public ObjectMapper getMapperWithCustomDeserializer() {
ObjectMapper objectMapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.setDeserializerModifier(new BeanDeserializerModifier() {
@Override
public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config,
BeanDescription beanDesc, JsonDeserializer<?> defaultDeserializer) {
if (beanDesc.getBeanClass() == User.class) {
return new UserDeserializer(defaultDeserializer);
} else {
return defaultDeserializer;
}
}
});
objectMapper.registerModule(module);
return objectMapper;
}
然后,自定义反序列化程序需要如下所示:
public class UserDeserializer extends DelegatingDeserializer {
public UserDeserializer(JsonDeserializer<?> delegate) {
super(delegate);
}
@Override
protected JsonDeserializer<?> newDelegatingInstance(JsonDeserializer<?> newDelegate) {
return new UserDeserializer(newDelegate);
}
@Override
public User deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException {
String key = p.getCurrentName();
User result = (User) super.deserialize(p, ctxt);
result.userId = key;
return result;
}
}
最后,您需要删除@JsonDeseriize
注释。然后,自定义反序列化器和@JsonBack参考应该可以工作。
I'va是一个OID接口,可以由许多具体类型实现: 现在我有一个具有两个字段的对象,一个使用抽象接口类型(OID)定义,另一个使用具体类型(MyOID)定义 我想使用jackson以不同的方式序列化/反序列化字段,无论它们是使用抽象接口类型还是具体类型定义的: 注意,被序列化,包括类型信息(多态序列化),而被序列化为文本 为此,我将OID接口注释为: 并为每个具体类型分配了类型id: 最后,对容器
我得到了。了解调用相同的反序列化器。是否有一种方法可以在custome反序列化器中使用或?
如何基于json中指定的类类型,在Jackson中实现从json到Java对象的转换。 Java类型示例:
问题内容: 我正在使用Flickr API 。调用该方法时,默认的JSON结果为: 我想将此响应解析为Java对象: JSON属性应按以下方式映射: 不幸的是,我无法找到一种使用Annotations做到这一点的好方法。到目前为止,我的方法是将JSON字符串读入a 并从中获取值。 但是我认为,这是有史以来最不优雅的方式。有没有简单的方法,可以使用注释还是自定义反序列化器? 这对我来说将是很明显的,
我想通过扩展默认的反序列化器来创建自己的反序列化器,在其后面设置更多的值: 如您所见,我还想将此DTO母类重用于其他DTO。 我没有找到任何这样的例子。我真的是世界上第一个 反序列化的“AsUsual”(p,ctxt)应该是什么 我应该使用什么motherclass?JsonDeserializer/StdDeserializer/UntypedObjectDeserializer 反序列化程序会
我想反序列化表单中的类: 其中文本是加密的,反序列化应该在重建TestFieldEncryptedMessage实例之前取消对值的加密。 我采用的方法非常类似于:https://github.com/codesqueak/jackson-json-crypto 也就是说,我正在构建一个扩展SimpleModule的模块: 如您所见,设置了两个修饰符:EncryptedSerializerModif