Spring @RestController 自定义 JSON 反序列化器

19

我希望为一些类(在此处是角色)使用自定义的JSON反序列化器,但我无法使其正常工作。自定义的反序列化器根本没有被调用。

我使用的是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
    }
}
  1. @JsonDeserialize on Role

    @JsonDeserialize(using = ModelDeserializer.class)
    public class Role extends Model {
    
    }
    
  2. Jackson2ObjectMapperBuilder bean in Java Config

    @Bean
    public Jackson2ObjectMapperBuilder jacksonBuilder() {
        Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
        builder.deserializerByType(Role.class, new ModelDeserializer());
        return builder;
    }
    

我做错了什么?

编辑 可能是由于@RestController,因为它与@Controller不同...

2个回答

25
首先,您不需要覆盖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;
    }
}

我需要做同样的事情,唯一不同的是我使用get方法,在我的pojo对象中使用@JsonDeserialize的Date类型。但是当我运行该方法时,我得到了一个http 400错误。(spring 4.1.7和jackson 2.7.4) - Hector

1

还有另一个相当有趣的解决方案,可以在调用默认反序列化器之前修改JSON正文,这可能会很有帮助。假设您需要使用一些附加的bean来完成此操作(使用@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);

           }

      }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接