杰克逊状态反序列化
Jackson Stateful Deserialization
我有一个 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 可能由 class 的实例提供,如下所示:
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 提供上述 class 的实例,并让 Jackson 在将其设置为打开之前使用此对象获取 newSystemId它创建的 POJO?
请注意,上面的 JSON 只是实际 JSON 的一小段,因此可能包含数百个上述对象。我想为每个反序列化提供一个 SystemIdProvider class 的新实例,因为它维护的 "state" 也基于它迄今为止遇到的 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;
要使 SystemIdProvider
在 DeserializationContext
中可用,请像这样调用 Jackson 的映射器:
ObjectMapper mapper = new ObjectMapper();
MyPojo deserialized = mapper.reader(MyPojo.class)
.withAttribute("systemIdProvider", new SystemIdProvider())
.readValue(json);
我有一个 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 可能由 class 的实例提供,如下所示:
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 提供上述 class 的实例,并让 Jackson 在将其设置为打开之前使用此对象获取 newSystemId它创建的 POJO?
请注意,上面的 JSON 只是实际 JSON 的一小段,因此可能包含数百个上述对象。我想为每个反序列化提供一个 SystemIdProvider class 的新实例,因为它维护的 "state" 也基于它迄今为止遇到的 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;
要使 SystemIdProvider
在 DeserializationContext
中可用,请像这样调用 Jackson 的映射器:
ObjectMapper mapper = new ObjectMapper();
MyPojo deserialized = mapper.reader(MyPojo.class)
.withAttribute("systemIdProvider", new SystemIdProvider())
.readValue(json);