[BAEL-2547] jackson deserialization class-casting exception

This commit is contained in:
Kent@lhind.hp.g5 2020-12-31 23:20:27 +01:00 committed by Kai Yuan
parent 3f29e25765
commit 1a2bd73487
6 changed files with 305 additions and 0 deletions

View File

@ -0,0 +1,70 @@
package com.baeldung.jackson.tocollection;
import java.util.Objects;
public class Book {
private Integer bookId;
private String title;
private String author;
public Book() {}
public Book(Integer bookId, String title, String author) {
this.bookId = bookId;
this.title = title;
this.author = author;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof Book)) {
return false;
}
Book book = (Book) o;
if (!Objects.equals(bookId, book.bookId)) {
return false;
}
if (!Objects.equals(title, book.title)) {
return false;
}
return Objects.equals(author, book.author);
}
@Override
public int hashCode() {
int result = bookId != null ? bookId.hashCode() : 0;
result = 31 * result + (title != null ? title.hashCode() : 0);
result = 31 * result + (author != null ? author.hashCode() : 0);
return result;
}
public Integer getBookId() {
return bookId;
}
public void setBookId(Integer bookId) {
this.bookId = bookId;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
}

View File

@ -0,0 +1,24 @@
package com.baeldung.jackson.tocollection;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.CollectionType;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class JsonToCollectionUtil {
private JsonToCollectionUtil(){}
public static <T> List<T> jsonArrayToList(String json, Class<T> elementClass) throws IOException {
ObjectMapper objectMapper = new ObjectMapper();
CollectionType listType = objectMapper.getTypeFactory().constructCollectionType(ArrayList.class, elementClass);
return objectMapper.readValue(json, listType);
}
public static <T> List<T> jsonArrayToList2(String json, Class<T> elementClass) throws IOException {
return new ObjectMapper().readValue(json, new TypeReference<List<T>>() {});
}
}

View File

@ -0,0 +1,13 @@
[ {
"bookId" : 1,
"title" : "A Song of Ice and Fire",
"author" : "George R. R. Martin"
}, {
"bookId" : 2,
"title" : "The Hitchhiker's Guide to the Galaxy",
"author" : "Douglas Adams"
}, {
"bookId" : 3,
"title" : "Hackers And Painters",
"author" : "Paul Graham"
} ]

View File

@ -0,0 +1,17 @@
<ArrayList>
<item>
<bookId>1</bookId>
<title>A Song of Ice and Fire</title>
<author>George R. R. Martin</author>
</item>
<item>
<bookId>2</bookId>
<title>The Hitchhiker's Guide to the Galaxy</title>
<author>Douglas Adams</author>
</item>
<item>
<bookId>3</bookId>
<title>Hackers And Painters</title>
<author>Paul Graham</author>
</item>
</ArrayList>

View File

@ -0,0 +1,130 @@
package com.baeldung.jackson.tocollection;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.CollectionType;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import org.assertj.core.util.Lists;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
public class DeserializeToJavaCollectionUnitTest {
private ObjectMapper objectMapper;
private XmlMapper xmlMapper;
private List<Book> expectedBookList;
@BeforeEach
void setup() {
objectMapper = new ObjectMapper();
xmlMapper = new XmlMapper();
expectedBookList = Lists.newArrayList(
new Book(1, "A Song of Ice and Fire", "George R. R. Martin"),
new Book(2, "The Hitchhiker's Guide to the Galaxy", "Douglas Adams"),
new Book(3, "Hackers And Painters", "Paul Graham"));
}
private String readFile(String path) {
try (Scanner scanner = new Scanner(getClass().getResourceAsStream(path), "UTF-8")) {
return scanner.useDelimiter("\\A").next();
}
}
/*====================
* JSON tests
*====================
*/
@Test
void givenJsonString_whenDeserializingToList_thenThrowingClassCastException() throws JsonProcessingException {
String jsonString = readFile("/to-java-collection/books.json");
List<Book> bookList = objectMapper.readValue(jsonString, ArrayList.class);
assertThat(bookList).size().isEqualTo(3);
assertThatExceptionOfType(ClassCastException.class)
.isThrownBy(() -> bookList.get(0).getBookId())
.withMessageMatching(".*java.util.LinkedHashMap cannot be cast to .*com.baeldung.jackson.tocollection.Book.*");
}
@Test
void givenJsonString_whenDeserializingWithTypeReference_thenGetExpectedList() throws JsonProcessingException {
String jsonString = readFile("/to-java-collection/books.json");
List<Book> bookList = objectMapper.readValue(jsonString, new TypeReference<List<Book>>() {});
assertThat(bookList.get(0)).isInstanceOf(Book.class);
assertThat(bookList).isEqualTo(expectedBookList);
}
@Test
void givenJsonString_whenDeserializingWithJavaType_thenGetExpectedList() throws JsonProcessingException {
String jsonString = readFile("/to-java-collection/books.json");
CollectionType listType = objectMapper.getTypeFactory().constructCollectionType(ArrayList.class, Book.class);
List<Book> bookList = objectMapper.readValue(jsonString, listType);
assertThat(bookList.get(0)).isInstanceOf(Book.class);
assertThat(bookList).isEqualTo(expectedBookList);
}
@Test
void givenJsonString_whenDeserializingWithConvertValueAndTypeReference_thenGetExpectedList() throws JsonProcessingException {
String jsonString = readFile("/to-java-collection/books.json");
JsonNode jsonNode = objectMapper.readTree(jsonString);
List<Book> bookList = objectMapper.convertValue(jsonNode, new TypeReference<List<Book>>() {});
assertThat(bookList.get(0)).isInstanceOf(Book.class);
assertThat(bookList).isEqualTo(expectedBookList);
}
@Test
void givenJsonString_whenDeserializingWithConvertValueAndJavaType_thenGetExpectedList() throws JsonProcessingException {
String jsonString = readFile("/to-java-collection/books.json");
JsonNode jsonNode = objectMapper.readTree(jsonString);
List<Book> bookList = objectMapper.convertValue(jsonNode, objectMapper.getTypeFactory().constructCollectionType(ArrayList.class, Book.class));
assertThat(bookList.get(0)).isInstanceOf(Book.class);
assertThat(bookList).isEqualTo(expectedBookList);
}
/*====================
* XML tests
*====================
*/
@Test
void givenXml_whenDeserializingToList_thenThrowingClassCastException() throws JsonProcessingException {
String xml = readFile("/to-java-collection/books.xml");
List<Book> bookList = xmlMapper.readValue(xml, ArrayList.class);
assertThat(bookList).size().isEqualTo(3);
assertThatExceptionOfType(ClassCastException.class)
.isThrownBy(() -> bookList.get(0).getBookId())
.withMessageMatching(".*java.util.LinkedHashMap cannot be cast to .*com.baeldung.jackson.tocollection.Book.*");
}
@Test
void givenXml_whenDeserializingWithTypeReference_thenGetExpectedList() throws JsonProcessingException {
String xml = readFile("/to-java-collection/books.xml");
List<Book> bookList = xmlMapper.readValue(xml, new TypeReference<List<Book>>() {});
assertThat(bookList.get(0)).isInstanceOf(Book.class);
assertThat(bookList).isEqualTo(expectedBookList);
}
@Test
void givenXml_whenDeserializingWithConvertValueAndTypeReference_thenGetExpectedList() throws JsonProcessingException {
String xml = readFile("/to-java-collection/books.xml");
List node = xmlMapper.readValue(xml, List.class);
List<Book> bookList = xmlMapper.convertValue(node, new TypeReference<List<Book>>() {});
assertThat(bookList.get(0)).isInstanceOf(Book.class);
assertThat(bookList).isEqualTo(expectedBookList);
}
@Test
void givenXml_whenDeserializingWithConvertValueAndJavaType_thenGetExpectedList() throws JsonProcessingException {
String xml = readFile("/to-java-collection/books.xml");
List node = xmlMapper.readValue(xml, List.class);
List<Book> bookList = xmlMapper.convertValue(node, objectMapper.getTypeFactory().constructCollectionType(ArrayList.class, Book.class));
assertThat(bookList.get(0)).isInstanceOf(Book.class);
assertThat(bookList).isEqualTo(expectedBookList);
}
}

View File

@ -0,0 +1,51 @@
package com.baeldung.jackson.tocollection;
import org.assertj.core.util.Lists;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.util.List;
import java.util.Scanner;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
class JsonToCollectionUtilUnitTest {
private List<Book> expectedBookList;
@BeforeEach
void setup() {
expectedBookList = Lists.newArrayList(
new Book(1, "A Song of Ice and Fire", "George R. R. Martin"),
new Book(2, "The Hitchhiker's Guide to the Galaxy", "Douglas Adams"),
new Book(3, "Hackers And Painters", "Paul Graham"));
}
private String readFile(String path) {
try (Scanner scanner = new Scanner(getClass().getResourceAsStream(path), "UTF-8")) {
return scanner.useDelimiter("\\A").next();
}
}
@Test
void givenJsonString_whenCalljsonArrayToList_thenGetExpectedList() throws IOException {
String jsonString = readFile("/to-java-collection/books.json");
List<Book> bookList = JsonToCollectionUtil.jsonArrayToList(jsonString, Book.class);
assertThat(bookList.get(0)).isInstanceOf(Book.class);
assertThat(bookList).isEqualTo(expectedBookList);
}
@Test
void givenJsonString_whenCalljsonArrayToList2_thenGetException() throws IOException {
String jsonString = readFile("/to-java-collection/books.json");
List<Book> bookList = JsonToCollectionUtil.jsonArrayToList2(jsonString, Book.class);
assertThat(bookList).size().isEqualTo(3);
assertThatExceptionOfType(ClassCastException.class)
.isThrownBy(() -> bookList.get(0).getBookId())
.withMessageMatching(".*java.util.LinkedHashMap cannot be cast to .*com.baeldung.jackson.tocollection.Book.*");
}
}