Spring MockMVC
JSON response
extract value
Java
unit testing

How to extract value from JSON response when using Spring MockMVC

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

When testing a Spring MVC or Spring Boot controller with MockMvc, you usually need one of two things from the JSON response: quick inline assertions or the actual value for later use in the test. The best tool depends on which of those goals you have, and the usual choices are jsonPath, MvcResult, and Jackson deserialization.

Use jsonPath for Direct Assertions

If you only need to verify that a field exists and has the expected value, jsonPath is the cleanest option. It keeps the whole assertion next to the request.

java
1import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
2import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
3import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
4
5mockMvc.perform(get("/api/users/1"))
6    .andExpect(status().isOk())
7    .andExpect(jsonPath("$.id").value(1))
8    .andExpect(jsonPath("$.name").value("Alice"))
9    .andExpect(jsonPath("$.address.city").value("Toronto"));

This is ideal when the extracted value does not need to leave the assertion chain.

Useful patterns include:

  • '$.id for a top-level field'
  • '$.address.city for a nested field'
  • '$[0].name for the first item in a returned array'

For simple verification, this is usually better than manually parsing the response body.

Use MvcResult When You Need the Value in Java Code

If you need to store a value and use it later in the test, call andReturn() and read the response body.

java
1import com.jayway.jsonpath.JsonPath;
2import org.springframework.test.web.servlet.MvcResult;
3
4MvcResult result = mockMvc.perform(get("/api/users/1"))
5    .andExpect(status().isOk())
6    .andReturn();
7
8String json = result.getResponse().getContentAsString();
9String name = JsonPath.read(json, "$.name");
10Integer id = JsonPath.read(json, "$.id");
11
12System.out.println(name);
13System.out.println(id);

This pattern is useful when a value from one response becomes input to a later request.

Deserialize the Whole Response for Typed Access

If the endpoint returns a structured object and you need several fields, parsing JSON into a DTO is often cleaner than reading many independent JSON paths.

java
1import com.fasterxml.jackson.databind.ObjectMapper;
2
3MvcResult result = mockMvc.perform(get("/api/users/1"))
4    .andExpect(status().isOk())
5    .andReturn();
6
7String json = result.getResponse().getContentAsString();
8ObjectMapper mapper = new ObjectMapper();
9UserResponse user = mapper.readValue(json, UserResponse.class);
10
11System.out.println(user.getName());
12System.out.println(user.getAddress().getCity());

This approach gives you compile-time field access and usually reads better when the response shape is non-trivial.

Example DTOs:

java
1public class UserResponse {
2    private Long id;
3    private String name;
4    private AddressResponse address;
5
6    public Long getId() { return id; }
7    public void setId(Long id) { this.id = id; }
8    public String getName() { return name; }
9    public void setName(String name) { this.name = name; }
10    public AddressResponse getAddress() { return address; }
11    public void setAddress(AddressResponse address) { this.address = address; }
12}
13
14public class AddressResponse {
15    private String city;
16
17    public String getCity() { return city; }
18    public void setCity(String city) { this.city = city; }
19}

Reuse Extracted Values in Later Requests

This is a common testing pattern for create-then-fetch flows.

java
1MvcResult createResult = mockMvc.perform(post("/api/users")
2        .contentType("application/json")
3        .content("""
4            {"name":"Bob"}
5            """))
6    .andExpect(status().isCreated())
7    .andReturn();
8
9String createJson = createResult.getResponse().getContentAsString();
10Integer userId = JsonPath.read(createJson, "$.id");
11
12mockMvc.perform(get("/api/users/" + userId))
13    .andExpect(status().isOk())
14    .andExpect(jsonPath("$.name").value("Bob"));

In this kind of test, extracting the raw value is more useful than just asserting it once.

Common Pitfalls

A common mistake is overusing getContentAsString() when jsonPath would have made the assertion shorter and clearer.

Another mistake is using jsonPath with the wrong expression syntax for arrays or nested objects. If an assertion fails unexpectedly, print the response body and verify the actual JSON structure first.

Developers also sometimes deserialize into the wrong DTO shape. If field names or nesting do not match the response payload, Jackson extraction fails even though the endpoint itself is fine.

Finally, remember that MockMvc gives you the raw response body as a string. If the response is not actually JSON, trying to read it with JSON tools will produce misleading test failures.

Summary

  • Use jsonPath for concise inline assertions on JSON fields.
  • Use MvcResult and getContentAsString() when you need the raw response body.
  • Parse the JSON with JsonPath when you need one or two extracted values in Java code.
  • Deserialize with Jackson when the response is better handled as a typed object.
  • Choose the approach based on whether you need quick assertions or reusable extracted data.

Related reading
Course
Intermediate
27 lessons
14 hours
OOD Fundamentals

Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.