Spring @RestController 사용자 지정 JSON 역직렬화기
일부 클래스(여기서 역할)에 사용자 지정 JSON deserializer를 사용하려고 하는데 작동할 수 없습니다.사용자 지정 역직렬화기가 호출되지 않았습니다.
Spring Boot 1.2를 사용합니다.
역직렬화기:
public class ModelDeserializer extends JsonDeserializer<Role> {
@Override
public Role deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
return null; // this is what should be called but it isn't
}
}
컨트롤러:
@RestController
public class RoleController {
@RequestMapping(value = "/role", method = RequestMethod.POST)
public Object createRole(Role role) {
// ... this is called
}
}
@JsonDeserialize
역할에 따라@JsonDeserialize(using = ModelDeserializer.class) public class Role extends Model { }
Jackson2ObjectMapperBuilder
Java 구성에서 been@Bean public Jackson2ObjectMapperBuilder jacksonBuilder() { Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder(); builder.deserializerByType(Role.class, new ModelDeserializer()); return builder; }
내가 뭘 잘못하고 있는 거지?
EDIT 아마도 원인일 것입니다.@RestController
와 함께 작동하기 때문에@Controller
...
무엇보다도 우선, 당신은 그것을 무시할 필요가 없습니다.Jackson2ObjectMapperBuilder
사용자 지정 역직렬화기를 추가합니다.추가할 수 없는 경우 이 접근 방식을 사용해야 합니다.@JsonDeserialize
주석사용해야 합니다.@JsonDeserialize
또는 오버라이드Jackson2ObjectMapperBuilder
.
놓친 것은@RequestBody
주석:
@RestController
public class JacksonCustomDesRestEndpoint {
@RequestMapping(value = "/role", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public Object createRole(@RequestBody Role role) {
return role;
}
}
@JsonDeserialize(using = RoleDeserializer.class)
public class Role {
// ......
}
public class RoleDeserializer extends JsonDeserializer<Role> {
@Override
public Role deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
// .................
return something;
}
}
기본 역직렬화기를 호출하기 전에 JSON 본문을 수정하려는 경우에 도움이 될 수 있는 매우 흥미로운 해결책도 있습니다.그리고 그것을 위해 약간의 추가적인 콩을 사용해야 한다고 상상해 봅시다. (사용).@Autowire
메커니즘)
다음과 같은 컨트롤러가 있다고 가정해 보겠습니다.
@RequestMapping(value = "/order/product", method = POST)
public <T extends OrderProductInterface> RestGenericResponse orderProduct(@RequestBody @Valid T data) {
orderService.orderProduct(data);
return generateResponse();
}
어디에OrderProductInterface
다음과 같습니다.
@JsonIgnoreProperties(ignoreUnknown = true)
@JsonSerialize(include = NON_EMPTY)
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, visible = true, property = "providerType")
@JsonSubTypes({
@JsonSubTypes.Type(value = OrderProductForARequestData.class, name = "A")
})
public interface OrderProductInterface{}
위의 코드는 파일 기반의 동적 역직렬화를 제공합니다.providerType
구체적인 구현에 따른 검증.더 잘 이해하기 위해 다음을 고려합니다.OrderProductForARequestData
다음과 같은 것이 될 수 있습니다.
public class OrderProductForARequestData implements OrderProductInterface {
@NotBlank(message = "is mandatory field.")
@Getter @Setter
private String providerId;
@NotBlank(message = "is mandatory field.")
@Getter @Setter
private String providerType;
@NotBlank(message = "is mandatory field.")
@Getter @Setter
private String productToOrder;
}
그리고 이제 우리가 어떻게든 그것을 하고 싶어하는 것을 상상해 봅시다.providerType
기본 역직렬화가 실행되기 전에 (임의 입력).그래서 객체는 의 규칙에 따라 적절하게 역직렬화됩니다.OrderProductInterface
그러기 위해서는 당신은 단지 당신의 것을 수정할 수 있습니다.@Configuration
클래스는 다음과 같습니다.
//here can be any annotation which will enable MVC/Boot
@Configuration
public class YourConfiguration{
@Autowired
private ObjectMapper mapper;
@Autowired
private ProviderService providerService;
@Override
public void setup() {
super.setup();
SimpleModule module = new SimpleModule();
module.setDeserializerModifier(new BeanDeserializerModifier() {
@Override
public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer<?> deserializer) {
if (beanDesc.getBeanClass() == OrderProductInterface.class) {
return new OrderProductInterfaceDeserializer(providerService, beanDesc);
}
return deserializer;
}
});
mapper.registerModule(module);
}
public static class OrderProductInterfaceDeserializer extends AbstractDeserializer {
private static final long serialVersionUID = 7923585097068641765L;
private final ProviderService providerService;
OrderProductInterfaceDeserializer(roviderService providerService, BeanDescription beanDescription) {
super(beanDescription);
this.providerService = providerService;
}
@Override
public Object deserializeWithType(JsonParser p, DeserializationContext context, TypeDeserializer typeDeserializer) throws IOException {
ObjectCodec oc = p.getCodec();
JsonNode node = oc.readTree(p);
//Let's image that we have some identifier for provider type and we want to detect it
JsonNode tmp = node.get("providerId");
Assert.notNull(tmp, "'providerId' is mandatory field");
String providerId = tmp.textValue();
Assert.hasText(providerId, "'providerId' can't be empty");
// Modify node
((ObjectNode) node).put("providerType",providerService.getProvider(providerId));
JsonFactory jsonFactory = new JsonFactory();
JsonParser newParser = jsonFactory.createParser(node.toString());
newParser.nextToken();
return super.deserializeWithType(newParser, context, typeDeserializer);
}
}
}
언급URL : https://stackoverflow.com/questions/27550376/spring-restcontroller-custom-json-deserializer
'programing' 카테고리의 다른 글
마우스 이동 시 업데이트되는 Vue.js 구성 요소 간의 상태 공유 (0) | 2023.07.02 |
---|---|
R 데이터 프레임에 행을 추가하는 방법 (0) | 2023.07.02 |
Mongodb - c# 드라이버로 특정 요소 포함 또는 제외 (0) | 2023.07.02 |
C# Excel Interop:값을 텍스트로 저장하는 셀 형식 지정 방법 (0) | 2023.07.02 |
maven 3.8.5가 있는 intelij Idea에서 Springboot 2.7 프로젝트를 가져오는 중 오류 발생했습니다. (0) | 2023.07.02 |