我正在开发一个Java库,以便能够读/写Lottie数据(定义为JSON的动画)。我试图用最少的代码和记录来实现这一点,但要为Lottie格式中定义的所有可能的用例实现这一点有点挑战性。我已经能够处理几乎所有的事情,但我仍然需要为关键帧找到一个合适的解决方案。
在下面的单元测试中,应该如何定义Java对象才能解析示例JSON?这在“pureJackson”中可能吗?还是需要一个helper类?我使用的是Jackson 2.14.1。
此时,只有testTimed
成功。
public class KeyframeTest {
private static final ObjectMapper mapper = new ObjectMapper();
@Test
void testInteger() throws JsonProcessingException {
var json = """
{
"k": [
128,
256
]
}
""";
var animated = mapper.readValue(json, Animated.class);
assertAll(
() -> assertEquals(2, animated.keyframes().size()),
() -> assertTrue(animated.keyframes().get(0) instanceof NumberKeyframe),
() -> assertEquals(128, animated.keyframes().get(0)),
() -> JSONAssert.assertEquals(json, mapper.writeValueAsString(animated), false)
);
}
@Test
void testDouble() throws JsonProcessingException {
var json = """
{
"k": [
5.01,
6.02
]
}
""";
var animated = mapper.readValue(json, Animated.class);
assertAll(
() -> assertEquals(2, animated.keyframes().size()),
() -> assertTrue(animated.keyframes().get(0) instanceof NumberKeyframe),
() -> assertEquals(5.01, animated.keyframes().get(0)),
() -> JSONAssert.assertEquals(json, mapper.writeValueAsString(animated), false)
);
}
@Test
void testTimed() throws JsonProcessingException {
var json = """
{
"k": [
{
"i": {
"x": [
0.833
],
"y": [
0.833
]
},
"o": {
"x": [
0.167
],
"y": [
0.167
]
},
"t": 60,
"s": [
1.1,
2.2,
3.3
]
},
{
"t": 60,
"s": [
360.0
]
}
]
}
""";
var animated = mapper.readValue(json, Animated.class);
assertAll(
() -> assertEquals(2, animated.keyframes().size()),
() -> assertTrue(animated.keyframes().get(0) instanceof TimedKeyframe),
() -> assertEquals(60, ((TimedKeyframe) animated.keyframes().get(0)).time()),
() -> JSONAssert.assertEquals(json, mapper.writeValueAsString(animated), false)
);
}
@Test
void testMixed() throws JsonProcessingException {
var json = """
{
"k": [
100,
33.44,
{
"t": 60,
"s": [
1.1,
2.2,
3.3
]
}
]
}
""";
var keyFrames = mapper.readValue(json, new TypeReference<List<Keyframe>>() {
});
assertAll(
() -> assertEquals(3, keyFrames.size()),
() -> assertTrue(keyFrames.get(0) instanceof NumberKeyframe),
() -> assertTrue(keyFrames.get(1) instanceof NumberKeyframe),
() -> assertTrue(keyFrames.get(2) instanceof TimedKeyframe),
() -> JSONAssert.assertEquals(json, mapper.writeValueAsString(keyFrames), false)
);
}
}
动画对象
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(Include.NON_NULL)
public record Animated(
@JsonProperty("a") Integer animated,
@JsonProperty("k") List<Keyframe> keyframes,
@JsonProperty("ix") Integer ix,
@JsonProperty("l") Integer l
) {
}
关键帧对象,基于我前面的问题使用Java记录使用fasterxml将JSON解析为Java记录。Jackson
@JsonTypeInfo(use = JsonTypeInfo.Id.DEDUCTION)
@JsonSubTypes({
@JsonSubTypes.Type(TimedKeyframe.class),
@JsonSubTypes.Type(NumberKeyframe.class)
})
public interface Keyframe {
}
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public record NumberKeyframe(
BigDecimal value
) implements Keyframe {
}
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(JsonInclude.Include.NON_NULL)
public record TimedKeyframe(
@JsonProperty("t") Integer time, // in frames
// Use BigDecimal here to be able to handle both Integer and Double
// https://stackoverflow.com/questions/40885065/jackson-mapper-integer-from-json-parsed-as-double-with-drong-precision
@JsonProperty("s") List<BigDecimal> values,
@JsonProperty("i") EasingHandle easingIn,
@JsonProperty("o") EasingHandle easingOut,
@JsonProperty("h") Integer holdFrame
) implements Keyframe {
}
这是testDouble的失败消息:
com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Could not resolve subtype of [simple type, class com.lottie4j.core.model.keyframe.Keyframe]: Unexpected input
at [Source: (String)"{
"k": [
5.01,
6.02
]
}
"; line: 3, column: 7] (through reference chain: com.lottie4j.core.model.Animated["k"]->java.util.ArrayList[0])
2条答案
按热度按时间6tdlim6h1#
看起来Jackson在将数字反序列化为对象时遇到了问题。您可以使用自定义反序列化器或通过将NumberKeyFrame扩展为BigDecimal来解决此问题。下面是一个工作的最小示例,但我删除了您的许多代码。请注意JsonTypeInfo注解中的defaultImpl。为了正常工作,这是必要的,尽管我不是100%为什么:see_no_evil:
rsaldnfx2#
Map似乎不正确。您得到的是:
这实际上是一个数字数组,我假设它应该Map到
NumberKeyframe
,但它会Map到如下内容:我不确定Jackson是否能在没有Map器的情况下无缝地完成这件事。