обработать InvalidTypeIdException с Джексоном - PullRequest
2 голосов
/ 16 марта 2020

Вот базовый класс, аннотированный 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;
    }
}

Ниже приведен класс, который переносится над классом и используется в контроллере. Этот класс-оболочка уже принимает «тип», который нужно передать классу выше

@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)
{    
    ...
}

Образец JSON, который работает с проверки контроллера при весенней загрузке -

{
  "type":"A",
  "base": {
     "type:"A",
     //fields of A
  }
}

Как можно удалить дубликат типа из внутренней базы, как показано ниже. это дает InvalidIdException от Джексона.

{
  "type":"A",
  "base": {
     //fields of A
  }
}

Я понимаю, что использование Custom Deserializer - это один из способов, но тогда JsonTypeInfo, JsonSubTypeInfo и все проверки, выполняемые по умолчанию, не применяются, и все должно быть создано вручную.

Можно ли установить требуемый тип дважды так, чтобы только внутренний тип Json распространялся на внутренний, и Джексон это понимал?

1 Ответ

1 голос
/ 16 марта 2020

Вы можете использовать JsonTypeInfo.As.EXTERNAL_PROPERTY, но примечание от javado c:

Механизм включения аналогичен PROPERTY, за исключением того, что свойство включено на один уровень выше в иерархии, т.е. уровень как JSON Объект для ввода. Обратите внимание, что этот выбор может использоваться только для свойств, но не для типов (классов). Попытка использовать его для классов приведет к стратегии включения вместо базового c 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;

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...