MixIn 不适用于标量值的 json 反序列化

问题描述 投票:0回答:1

我正在尝试使用 jackson 并使用以下混合从 json 标量字符串反序列化来自 Threetenextra 库的 YearWeek

import org.threeten.extra.YearWeek;
import com.fasterxml.jackson.annotation.JsonCreator;

public class YearWeekMixIn {
    @JsonCreator
    public static YearWeek parse(String value) {
        return YearWeek.parse(value);
    }
}

但是以下测试失败:

public class YearWeekMixInTest {

    public record Foo(YearWeek yearWeek) {}
    
    @Test
    public void foo() throws JsonMappingException, JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.addMixIn(YearWeek.class, YearWeekMixIn.class);
        
        objectMapper.readValue("{\"yearWeek\": \"2011-W01\"}", Foo.class);
    }
}

我收到以下异常:

com.fasterxml.jackson.databind.exc.InvalidDefinitionException:无法构造

org.threeten.extra.YearWeek
的实例(不存在创建者,如默认构造函数):没有从字符串值反序列化的字符串参数构造函数/工厂方法('2011-W01' )

mixin 中缺少什么来让 jackson 知道它应该使用 mixin 中带注释的方法进行反序列化?

java json jackson
1个回答
0
投票

jackson 的 mixin 不支持工厂方法。 所以我认为它还有另外两个解决方案供您使用。

解决方案1(使用StdConverter,且无需配置ObjectMapper)

class YearWeekConverter extends StdConverter<String, YearWeek> {
    @Override
    public YearWeek convert(String s) {
        return YearWeek.parse(s);
    }
}

record Foo(@JsonDeserialize(converter = YearWeekConverter.class) YearWeek yearWeek) {}

解决方案2(使用StdDeserializer)

class YearWeekDeserializer extends StdDeserializer<YearWeek> {

    public YearWeekDeserializer() {
        this(null);
    }

    public YearWeekDeserializer(Class<?> vc) {
        super(vc);
    }

    @Override
    public YearWeek deserialize(JsonParser jp, DeserializationContext ctxt)
            throws IOException, JsonProcessingException {
        final String s = jp.readValueAs(String.class);
        return YearWeek.parse(s);
    }
}

public class YearWeekMixInTest {

    public record Foo(YearWeek yearWeek) {}
    
    @Test
    public void foo() throws JsonMappingException, JsonProcessingException {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.addMixIn(YearWeek.class, YearWeekMixIn.class);

        // add module
        SimpleModule module = new SimpleModule();
        module.addDeserializer(YearWeek.class, new YearWeekDeserializer());
        objectMapper.registerModule(module);

        objectMapper.readValue("{\"yearWeek\": \"2011-W01\"}", Foo.class);
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.