为了账号安全,请及时绑定邮箱和手机立即绑定

Jackson:如何让@JsonBackReference 和自定义反序列化器同时工作?

Jackson:如何让@JsonBackReference 和自定义反序列化器同时工作?

慕运维8079593 2022-11-02 10:41:44
我有一个 JSON 结构,其中包含字符串到对象的映射:{    "domains": {        "ldap": {            "users": {                "fwalther": {                    "firstName": "Fritz",                    "lastName": "Walther"                },                // ...            }        }    },    // ...}       我想将此结构反序列化为使用 Jackson 的对象,Domain并且User我希望每个用户都有一个对其映射键(即用户 ID)和Domain容器的反向引用。这两种方法都有效,但如果我尝试同时获取两个反向引用,它就会失败。@JsonManagedReference带有和的 Java 类@JsonBackReference: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 时会出现以下异常:查看引发异常的代码,我发现我需要findBackReference在我的自定义反序列化器中实现,但我不知道如何,我也找不到这方面的信息。有任何想法吗?还是有其他方法可以同时获取映射键和对包含对象的反向引用?
查看完整描述

1 回答

?
郎朗坤

TA贡献1921条经验 获得超9个赞

在这个答案的帮助下,我找到了解决方案:自定义反序列化器需要基于默认反序列化器,它正确实现了反向引用机制。

这比仅仅从正确的基类继承要复杂一些。相反,您需要通过自定义获取(完全配置的)默认反序列化器实例BeanDeserializerModifier,然后将此实例传递给您的子类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;

    }

}

最后,您需要删除@JsonDeserialize注释。然后,自定义反序列化器和@JsonBackReference应该工作。


查看完整回答
反对 回复 2022-11-02
  • 1 回答
  • 0 关注
  • 87 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信