当前位置: 代码迷 >> java >> 杰克逊状态反序列化
  详细解决方案

杰克逊状态反序列化

热度:118   发布时间:2023-07-16 17:42:57.0

我有一个类似以下的JSON:

{
    systemId: 7
    name: "Phil"
    data: "XYZ"

    pointers: [
        {
            systemId: 23
            name: "Peter"
        },
        {
            systemId: 27
            name: "Jeroen"
        }
    ]
}

在上述JSON的POJO中,所有字段都是最终字段。 现在,在反序列化期间,我希望能够修改Jackson的POJO上设置的systemId字段之前。 此外,更改后的systemId实际上将由有状态对象根据JSON中的当前systemId提供。 例如,要在反序列化POJO上设置的新systemId可能由如下类的实例提供:

public class SystemIdProvider {
    ...
    public long getNewSystemId(long oldSystemId) {
        // do something with the oldSystemId and
        // the current state of this object to get the newSystemId
        return newSystemId;
    }
}

当它反序列化JSON时,有什么方法可以向Jackson提供上述类的实例,并让Jackson在创建的POJO上设置此对象之前使用此对象获取newSystemId吗?

请注意,上面的JSON只是实际JSON的一小段,因此可能包含数百个上述对象。 我想针对每个反序列化提供一个SystemIdProvider类的NEW实例,因为它维护的“状态”也基于迄今为止所遇到的systemIds。 因此,对于每个反序列化,都需要从一个干净的状态开始。

任何输入表示赞赏。

您需要为此编写一个自定义解串器。 假设您具有以下POJO:

public class MyPojo {

    private final long systemId;
    private final String foo;

    public MyPojo(long systemId, String foo) {
        this.systemId = systemId;
        this.foo = foo;
    }

    // getters and other methods
}

systemId字段编写一个自定义反序列化器:

public class SystemIdDeserializer extends StdDeserializer<Long> {

    public SystemIdDeserializer() {
        super(Long.class);
    }

    @Override
    public Long deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        SystemIdProvider systemIdProvider = (SystemIdProvider) ctxt.getAttribute("systemIdProvider");
        Long oldSystemId = _parseLong(jp, ctxt);
        return systemIdProvider.getNewSystemId(oldSystemId);
    }
}

systemId字段上使用@JsonDeserialize批注注册反序列化器:

@JsonDeserialize(using = SystemIdDeserializer.class)
private final long systemId;

为了使SystemIdProviderDeserializationContext可用,请像下面这样调用Jackson的映射器:

ObjectMapper mapper = new ObjectMapper();
MyPojo deserialized = mapper.reader(MyPojo.class)
        .withAttribute("systemIdProvider", new SystemIdProvider())
        .readValue(json);
  相关解决方案