Reputation: 603
I am using the spring boot version 2.3.3, below is my pom.xml.
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.group</groupId>
<artifactId>artifact</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>project</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.json/json -->
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20190722</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
I have a custom class/model.
public class Summary {
// attributes
//constructor
// getters/setters for each attributes
}
Its repository (interface and implementation)
public interface SummaryRepository {
List<Summary> getSummaryData(Date date);
}
@Repository
@Transactional
public class SummaryRepositoryImpl implements SummaryRepository {
@PersistenceContext
EntityManager entityManager;
@Override
public List<Summary> getSummaryData(Date date) {
// Implementation
}
}
In the controller, I am having the following code:
@RestController
public class SummaryController {
@Autowired
private SummaryRepository summaryRepository;
@RequestMapping(
value ="/summary-data",
method = RequestMethod.POST,
consumes = "application/json",
produces = MediaType.APPLICATION_JSON_VALUE
)
public ResponseEntity<List<Summary>> getSummaryData(@RequestBody RequestConfig requestConfig ) {
String dateStr = requestConfig.getDate();
Date date = new Date();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
try {
date = formatter.parse(dateStr);
} catch (Exception e) {
System.out.println("Exception: " + e.getMessage());
}
// Some logic
List<Summary> summaries = summaryRepository.getSummaryData(date);
if (summaries.size() > 0 ) {
return ResponseEntity.ok(summaries);
} else {
return ResponseEntity.notFound().build();
}
}
}
When I go to postman and send the POST request to above, I get the output as below:
[["2020-07-31", <values>],["2020-07-31",<values2>],["2020-07-31", <values3>],["2020-07-31",<values4>]]
i.e. literal list of object.
I am looking to get it in Json; something like:
[
{ "date": "2020-07-31", "attr2": "value2", "attr3": "value3" },
{ "date": "2020-07-31", "attr2": "value21", "attr3": "value31" },
{ "date": "2020-07-31", "attr2": "value12", "attr3": "value13" },
{ "date": "2020-07-31", "attr2": "value2", "attr3": "value3" }
]
i.e. "date", "attr2", etc are my attributes of the Summary (already defined with getters/setters).
What is missing here?
--------UPDATE---------
Based on the below response I have my SummaryResponse class.
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;
public class SummaryResponse {
@JsonProperty(value = "summary", required = true)
List<Summary> summaryList;
public SummaryResponse() {
}
public List<Summary> getSummaryList() {
return summaryList;
}
public void setSummaryList(List<Summary> summaryList) {
this.summaryList = summaryList;
}
}
I changed my controller logic to return this object.
@RequestMapping(
value ="/summary-data",
method = RequestMethod.POST,
consumes = "application/json"
)
public ResponseEntity<SummaryResponse> getSummaryData(@RequestBody RequestConfig requestConfig ) {
// Logic
List<Summary> summaries = summaryRepository.getSummaryData(date);
SummaryResponse summaryResponse = new SummaryResponse();
summaryResponse.setSummaryList(summaries);
if (summaries.size() > 0 ) {
return new ResponseEntity<>(summaryResponse, HttpStatus.OK);
} else {
return ResponseEntity.notFound().build();
}
}
Still I am not getting the JSON output. It is still Array of attributes.
{"summary":[["2020-07-31","attr2_value","attr3_value", null, "attr5_value"] ,["2020-07-31","attr2_value","attr3_value","attr4_value","attr5_value"]]}
What exactly is the issue here?
I am looking something like below:
[
{ "date": "2020-07-31", "attr2": "attr2_value", "attr3": "attr3_value", "attr4", null, "attr5": "attr5_value" },
{ "date": "2020-07-31", "attr2": "attr2_value", "attr3": "attr3_value", "attr4", "attr4_value", "attr5": "attr5_value" }
]
------------------UPDATE 2: Found the issue.----------------
Thanks for the hints, I got the issue.
In my Repository, I am using the native query where class is not entity.
List<Summary> summaryList = query.getResultList();
return summaryList;
Although I am taking the result in summaryList, it is actually a Object[] and not List. (Didn't knew this, new to spring boot and JPA).
So although my Controller is passing this (summaryList) to response it is actually a Object[].
My Summary Class is not a Entity (does not come from table or has identity), so changed my repository method:
List<Object> result = (List<Object>) query.getResultList();
Iterator it = result.iterator();
List<Summary> summaryList = new ArrayList<>();
while (it.hasNext()) {
Object[] row = (Object[]) it.next();
Summary summary = new Summary();
summary.setDate( (Date) row[0]);
summary.setName(String.valueOf(row[1]));
summary.setAccount(String.valueOf(row[2]));
...
...
// and so on
summaryList.add(summary);
}
Finally it is working as expected.
Upvotes: 2
Views: 24122
Reputation: 1376
Check your Summary class.
Based on the http responses you shared, the issue should be there - or at least you should be able to fix it there by adding jackson annotations.
You use a Date type inside your Summary class, which acts strange. If you use regular Date (import java.util.Date;) your response JSON response should look like this:
{
"id": "1",
"name": "Ball",
"date": "2020-10-09T19:05:17.189+00:00"
}
But your JSON has a short String representation of the date: "date": "2020-07-31".
So maybe inside your Summary class you import a Date class, which is not properly supported by Jackson.
Try to remove the date attribute and then check again your JSON response.
Instead of returning the List, just return one element of this List.
This should help you to find your problem.
I wrote this German blog post about handling JSON with Jackson in a Spring RestController - as it is the default in Spring Boot:
https://agile-coding.blogspot.com/2020/10/rest-json-apis-in-java-leicht-gemacht.html
Upvotes: 0
Reputation: 79
There are multiple ways to achieve this. You could write your own response class and add Jackson annotations. You need to do the same for the Summary class.
public class MyResponse {
@JsonProperty(value = "summary", required = true)
List<Summary> summaryList;
public List<Summary> getSummaryList() {
return summaryList;
}
public void setSummaryList(List<Summary> summaryList) {
this.summaryList = summaryList;
}
}
Make sure you have the Jackson dependency:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
Upvotes: 1