StringHttpMessageConverter.canWrite(String.class, APPLICATION_JSON) shouldn't return true, It will take over before other actual json converters. https://github.com/spring-projects/spring-framework/blob/708e61a7efbe727f91cc385c8d70a31f2fb0e972/spring-webmvc/src/main/java/org/springframework/web/servlet/config/annotation/WebMvcConfigurationSupport.java#L901-L965

here is test case:

@RestController
@RequestMapping("/echo")
public class EchoController {
    @PostMapping(consumes = { TEXT_PLAIN_VALUE, APPLICATION_JSON_VALUE }, produces = { TEXT_PLAIN_VALUE,
            APPLICATION_JSON_VALUE })
    public String echo(@RequestBody String string) {
        return "echo:" + string;
    }
}

@SpringBootTest(webEnvironment = WebEnvironment.MOCK)
@AutoConfigureMockMvc
class EchoControllerTests {
    @Autowired
    MockMvc mockMvc;
    @Test
    void acceptText() throws Exception {
        mockMvc.perform(post("/echo").contentType(TEXT_PLAIN).accept(TEXT_PLAIN).content("test"))
                .andExpect(status().isOk()).andExpect(content().string("echo:test"));
    }
    @Test
    void acceptJson() throws Exception {
        mockMvc.perform(post("/echo").contentType(TEXT_PLAIN).accept(APPLICATION_JSON).content("test"))
                .andExpect(status().isOk()).andExpect(content().json("\"echo:test\""));
        // test failed, content is echo:test, not converted to valid json "echo:test"
    }
}

Comment From: rstoyanchev

This is by design. StringHttpMessageConverter writes a String with any content type, similar to ByteArrayHttpMessageConverter. The String or byte[] is serialized content. For JSON serialization you need an Object or Map as a top-level container.