jackson Java Json枚举反序列化

xqnpmsa8  于 2023-10-20  发布在  Java
关注(0)|答案(2)|浏览(158)

JSON枚举反序列化不起作用。
接口:

@JsonTypeInfo(
        use = JsonTypeInfo.Id.NAME,
        include = JsonTypeInfo.As.PROPERTY,
        property="rlType"
)
@JsonSubTypes({
        @JsonSubTypes.Type(value = B.class)
})
public interface IA {
}

B级

@JsonTypeInfo(use = JsonTypeInfo.Id.NONE)
public enum B implements IA {
    X,
    Y,
    Z
}

设置

public record Settings(IA rlType, int myint1, int myint2) {}

下面是我想如何使用它的一个单元测试:

@Test
void testDeserialization() throws Exception {
        String json = """
            {
                "rlType": "X",
                "myint1": 5,
                "myint2": 10
            }
        """;
        ObjectMapper objectMapper = new ObjectMapper();
        RateLimiterSettings settings = objectMapper.readValue(json, Settings.class);

我得到以下错误:
com.fasterxml.jackson.databind.exc.InvalidTypeIdException:无法解析[简单类型,IA类]的子类型:缺少类型id属性“tlType”(用于POJO属性“rlType”),位于[Source:(String)”{“rlType”:“X”,“myint 1”:5,“myint 2”:10 }“;行:2,列:19](通过参考链:设置[“rlType”])
我尝试使用Settings(**B** rlType, int myint1, int myint2),它的工作,但我想这样做的接口。我错过了什么?
当我将对象写入json字符串时,我得到:{“rlType”:[“B”,“X”],..} -为什么是数组?

6g8kf2rb

6g8kf2rb1#

同时,我们发现接口是必要的,这个解决方案将工作:

@JsonTypeInfo(use = Id.NAME, include = As.PROPERTY, property="riType")
    @JsonSubTypes({ @JsonSubTypes.Type(B.class) })
    public interface IA {
    }

    public enum B implements IA {
        X,
        Y,
        Z
    }
    
    public record Settings(IA key, int myint1, int myint2)
    {
        
    }
    
    @Test
    void testJson() throws Exception
    {
        String json = """
                {
                "key": ["B", "X"],
                "myint1":"1",
                "myint2":"2"
                }
                """;
        System.out.println(new ObjectMapper().readValue(json, Settings.class));
    }

显然,Jackson使用不同的语法来序列化枚举值和普通类。对于枚举示例,只使用["type", "value"],对于类示例,使用完整的对象表示法{ "riType":..., "property":"value", etc. }

wgmfuz8q

wgmfuz8q2#

我可以用JsonDeserializer解决这个问题。

public class IADeserializer extends JsonDeserializer<IA> {

    @Override
    public IA deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        String typeName = p.getValueAsString();

        // Try to match with the first enum
        try {
            return B.valueOf(typeName);
        } catch (IllegalArgumentException e) {
            // Ignored
        }

        // Try to match with the second enum
        try {
            return C.valueOf(typeName);
        } catch (IllegalArgumentException e) {
            // Ignored
        }

        // Handle case where the value doesn't match any known enum
        throw new IOException("Invalid rlType value: " + typeName);
    }
}

@JsonDeserialize(using = IADeserializer.class)
    public interface IRateLimiterType {
}

相关问题