英文:
handle InvalidTypeIdException with jackson
问题
以下是已翻译的内容:
这是一个使用@JsonType和@JsonSubTypes进行注释的基类,其中需要一个必填的“type”字段。
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type", visible = true)
@JsonSubTypes(value = {
@JsonSubTypes.Type(value = SubA.class, name = "A"),
@JsonSubTypes.Type(value = SubB.class, name = "B")
})
public abstract class Base {
private String type;
public String getType()
{
return type;
}
public void setType(String type)
{
this.type = type;
}
}
下面是一个将上述类封装并在控制器中使用的类。这个封装类已经带有需要传递给上面的Base类的“type”。
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
class BaseWrapper {
@NotBlank
private String type;
@NotNull
@Valid
private Base base;
}
最后,在控制器中进行了验证。
@PostMapping("/createBase")
public ResponseEntity<ResponseDto> createBase(@RequestBody @Valid BaseWrapper)
{
// ...
}
下面是一个在Spring Boot中与控制器验证一起使用的示例JSON:
{
"type":"A",
"base": {
"type":"A",
//字段A的内容
}
}
如何才能像下面这样从基类内部移除重复的type呢?这会导致Jackson抛出InvalidIdException
。
{
"type":"A",
"base": {
//字段A的内容
}
}
我理解使用自定义反序列化器是一种方法,但这样一来,默认执行的JsonTypeInfo、JsonSubTypeInfo和所有验证将不再生效,而且需要手动编写所有内容。
是否有办法修复重复的type字段,以便只传播外部的Json type给内部,让Jackson能够理解呢?
英文:
Here is Base class annotated with JsonType and JsonSubTypes with mandatory "type" field required.
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type", visible = true)
@JsonSubTypes(value = {
@JsonSubTypes.Type(value = SubA.class, name = "A"),
@JsonSubTypes.Type(value = SubB.class, name = "B")
})
public abstract class Base {
private String type;
public String getType()
{
return type;
}
public void setType(String type)
{
this.type = type;
}
}
There is below class which wraps above class and is used in controller. This wrapper class is taking "type" already which need to be passed to class Base above
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
class BaseWrapper {
@NotBlank
private String type;
@NotNull
@Valid
private Base base;
}
Finally , validation are here in controller
@PostMapping("/createBase")
public ResponseEntity<ResponseDto> createBase(@RequestBody @Valid BaseWrapper)
{
...
}
Sample JSON that works with controller validations in spring boot -
{
"type":"A",
"base": {
"type:"A",
//fields of A
}
}
How can the duplicate type be removed from inside base itself like below. this gives InvalidIdException
from Jackson.
{
"type":"A",
"base": {
//fields of A
}
}
I understand using Custom Deserializer is one way but then JsonTypeInfo, JsonSubTypeInfo and all validations being done by default does not apply and everything has to be hand-crafted.
Can the type required twice be fixed so that only outer Json type is propagated to inner and Jackson understands it ?
答案1
得分: 1
你可以使用 JsonTypeInfo.As.EXTERNAL_PROPERTY
,但请注意来自 javadoc 的说明:
> 类似于 PROPERTY 的包含机制,不同之处在于属性在层次结构中包含得更高,即作为与 JSON 对象类型处于同一级别的同级属性。请注意,此选择只能用于属性,而不能用于类型(类)。尝试将其用于类将导致基本 PROPERTY 的包含策略。
因此,这将不适用于类级别,而适用于包装器中的属性。
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
@Getter
@Setter
public static class BaseWrapper {
@NotBlank
private String type;
@NotNull
@Valid
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "type", visible = true)
@JsonSubTypes(value = {
@JsonSubTypes.Type(value = SubA.class, name = "A"),
@JsonSubTypes.Type(value = SubB.class, name = "B")
})
private Base base;
}
英文:
You can use JsonTypeInfo.As.EXTERNAL_PROPERTY
but note from javadoc:
> Inclusion mechanism similar to PROPERTY, except that property is
> included one-level higher in hierarchy, i.e. as sibling property at
> same level as JSON Object to type. Note that this choice can only be
> used for properties, not for types (classes). Trying to use it for
> classes will result in inclusion strategy of basic PROPERTY instead.
So this will not work on class level but on property in wrapper
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
@Getter
@Setter
public static class BaseWrapper {
@NotBlank
private String type;
@NotNull
@Valid
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.EXTERNAL_PROPERTY, property = "type", visible = true)
@JsonSubTypes(value = {
@JsonSubTypes.Type(value = SubA.class, name = "A"),
@JsonSubTypes.Type(value = SubB.class, name = "B")
})
private Base base;
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论