java - Jackson JsonDeserializer 将字段的反序列化委托(delegate)回该字段类型的默认反序列化器

标签 java jackson jackson2 jackson-databind

给定

public class ConstraintMatch {
    protected String constraintName;
    protected Score score;
    ...
}

我在 jackson 有以下序列化器:

public class ConstraintMatchJacksonJsonSerializer extends JsonSerializer<ConstraintMatch> {

    @Override
    public void serialize(ConstraintMatch constraintMatch, JsonGenerator generator, SerializerProvider serializers)
            throws IOException {
        generator.writeStartObject();
        generator.writeStringField("constraintName", constraintMatch.getConstraintName());
        generator.writeFieldName("score");
        // Delegate to serialization to the default Score serializer
        serializers.findValueSerializer(Score.class)
                 .serialize(constraintMatch.getScore(), generator, serializers);
        generator.writeEndObject();
    }

}

如何编写一个也委托(delegate)给默认反序列化器的反序列化器?

public class ConstraintMatchJacksonJsonDeserializer extends JsonDeserializer<ConstraintMatch> {

    @Override
    public ConstraintMatch deserialize(JsonParser parser, DeserializationContext context) throws IOException {
        JsonNode tree = parser.readValueAsTree();

        String constraintName = tree.get("constraintName").asText();

        JsonNode scoreNode = tree.get("score");
        Score score = ...; // How do I delegate to the default deserializer?
        return new ConstraintMatch(constraintName, score);
    }

}

我查看了 findContextualValueDeserializer() 等,但无法创建 BeanProperty 实例。

最佳答案

在类似的情况下,我实际上发现有两个问题需要解决。首先,正如您所说,需要委托(delegate)回普通的解串器。但我遇到的另一个问题是如何将 JsonNode(下面的 TreeNode)提供给下一个反序列化(JsonParser,...)。

以下是该情况的工作示例,我想先行查找以找出子类。

希望这里的节点是你的scoreNode。听起来 objectClass 对你来说就是 Score.class。

@Override
public T deserialize(JsonParser parser, DeserializationContext ctxt)
        throws IOException, JsonProcessingException {
    ObjectMapper mapper = (ObjectMapper) parser.getCodec();
    TreeNode node = parser.readValueAsTree();

    // Select the subclass to deserialize as
    Class<? extends T> objectClass = deduceClass(node);

    // This based on ObjectMapper._convert()
    // - the problem here was the JsonParser (parser) had gone past the current node
    TokenBuffer buf = new TokenBuffer(mapper, false);
    SerializationConfig config = mapper.getSerializationConfig()
            .without(SerializationFeature.WRAP_ROOT_VALUE);
    DefaultSerializerProvider serializerProvider = ((DefaultSerializerProvider) mapper
            .getSerializerProvider()).createInstance(config,
                    mapper.getSerializerFactory());
    serializerProvider.serializeValue(buf, node);
    JsonParser nestedParser = buf.asParser();
    nestedParser.nextToken();
    JsonDeserializer<Object> deserializer = ctxt
            .findRootValueDeserializer(
                    mapper.getTypeFactory().constructType(objectClass));
    @SuppressWarnings("unchecked")
    T obj = (T) deserializer.deserialize(nestedParser, ctxt);

    return obj;

}

(以防万一,这是 Jackson 2.7.9 的情况)

我很高兴听到从节点创建 JsonParser 的更简单方法。

关于java - Jackson JsonDeserializer 将字段的反序列化委托(delegate)回该字段类型的默认反序列化器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49240837/

相关文章:

java - 我们可以通过 URLConnection 传递多少数据?

java - 使用 Jackson 注解从 JSON 转换

java - map 上的 jackson 补丁对象

java - 使用注释的 Jackson 多态反序列化

Java解析多个文件

java - java生产者消费者模式如何出现死锁和饥饿问题?

java - 称为soap web 服务,它返回一个zip 文件作为附件。如何解压到内存中?

java - 将 String 属性序列化为嵌套 JSON 对象

java - 具有不常见 getter 方法名称的序列化中的 Jackson 命名约定问题

java - JSON 响应使用 Jackson 和 JAX-RS 异常映射器转义了引号