Add source code for article BAEL-2463 (#7543)

This commit is contained in:
Yavuz Tas 2019-08-11 18:27:36 +02:00 committed by KevinGilmore
parent 32127cc5b5
commit 9cb93861d9
9 changed files with 458 additions and 0 deletions

View File

@ -0,0 +1,25 @@
package com.baeldung.jackson.entities;
public class File {
private Long id;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@ -0,0 +1,82 @@
package com.baeldung.jackson.entities;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonIgnore;
public class Folder {
private Long id;
private String name;
private String owner;
private Date created;
private Date modified;
private Date lastAccess;
@JsonIgnore
private List<File> files = new ArrayList<>();
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getOwner() {
return owner;
}
public void setOwner(String owner) {
this.owner = owner;
}
public Date getCreated() {
return created;
}
public void setCreated(Date created) {
this.created = created;
}
public Date getModified() {
return modified;
}
public void setModified(Date modified) {
this.modified = modified;
}
public Date getLastAccess() {
return lastAccess;
}
public void setLastAccess(Date lastAccess) {
this.lastAccess = lastAccess;
}
public List<File> getFiles() {
return files;
}
public void setFiles(List<File> files) {
this.files = files;
}
}

View File

@ -0,0 +1,21 @@
package com.baeldung.jackson.serialization.custom.serializer;
import com.baeldung.jackson.entities.Folder;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializationConfig;
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
public class FolderBeanSerializerModifier extends BeanSerializerModifier {
@Override
public JsonSerializer<?> modifySerializer(SerializationConfig config, BeanDescription beanDesc, JsonSerializer<?> serializer) {
if (beanDesc.getBeanClass().equals(Folder.class)) {
return new FolderSerializerWithDefaultSerializerStored((JsonSerializer<Object>) serializer);
}
return serializer;
}
}

View File

@ -0,0 +1,36 @@
package com.baeldung.jackson.serialization.custom.serializer;
import java.io.IOException;
import com.baeldung.jackson.entities.File;
import com.baeldung.jackson.entities.Folder;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
public class FolderSerializer extends StdSerializer<Folder> {
public FolderSerializer() {
super(Folder.class);
}
@Override
public void serialize(Folder value, JsonGenerator gen, SerializerProvider provider) throws IOException {
gen.writeStartObject();
gen.writeStringField("name", value.getName());
gen.writeArrayFieldStart("files");
for (File file : value.getFiles()) {
gen.writeStartObject();
gen.writeNumberField("id", file.getId());
gen.writeStringField("name", file.getName());
gen.writeEndObject();
}
gen.writeEndArray();
gen.writeEndObject();
}
}

View File

@ -0,0 +1,30 @@
package com.baeldung.jackson.serialization.custom.serializer;
import java.io.IOException;
import com.baeldung.jackson.entities.Folder;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
public class FolderSerializerWithCallingOwnSerializer extends StdSerializer<Folder> {
public FolderSerializerWithCallingOwnSerializer() {
super(Folder.class);
}
@Override
public void serialize(Folder value, JsonGenerator gen, SerializerProvider provider) throws IOException {
gen.writeStartObject();
gen.writeStringField("name", value.getName());
provider.defaultSerializeField("files", value.getFiles(), gen);
provider.defaultSerializeField("details", value, gen);
gen.writeEndObject();
}
}

View File

@ -0,0 +1,35 @@
package com.baeldung.jackson.serialization.custom.serializer;
import java.io.IOException;
import com.baeldung.jackson.entities.Folder;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
public class FolderSerializerWithDefaultSerializerStored extends StdSerializer<Folder> {
private final JsonSerializer<Object> defaultSerializer;
public FolderSerializerWithDefaultSerializerStored(JsonSerializer<Object> defaultSerializer) {
super(Folder.class);
this.defaultSerializer = defaultSerializer;
}
@Override
public void serialize(Folder value, JsonGenerator gen, SerializerProvider provider) throws IOException {
gen.writeStartObject();
gen.writeStringField("name", value.getName());
provider.defaultSerializeField("files", value.getFiles(), gen);
gen.writeFieldName("details");
defaultSerializer.serialize(value, gen, provider);
gen.writeEndObject();
}
}

View File

@ -0,0 +1,34 @@
package com.baeldung.jackson.serialization.custom.serializer;
import java.io.IOException;
import com.baeldung.jackson.entities.Folder;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
public class FolderSerializerWithInternalObjectMapper extends StdSerializer<Folder> {
public FolderSerializerWithInternalObjectMapper() {
super(Folder.class);
}
@Override
public void serialize(Folder value, JsonGenerator gen, SerializerProvider provider) throws IOException {
gen.writeStartObject();
gen.writeStringField("name", value.getName());
// we access internal mapper to delegate the serialization of File list
ObjectMapper mapper = (ObjectMapper) gen.getCodec();
gen.writeFieldName("files");
String stringValue = mapper.writeValueAsString(value.getFiles());
gen.writeRawValue(stringValue);
gen.writeEndObject();
}
}

View File

@ -0,0 +1,29 @@
package com.baeldung.jackson.serialization.custom.serializer;
import java.io.IOException;
import com.baeldung.jackson.entities.Folder;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
public class FolderSerializerWithSerializerProvider extends StdSerializer<Folder> {
public FolderSerializerWithSerializerProvider() {
super(Folder.class);
}
@Override
public void serialize(Folder value, JsonGenerator gen, SerializerProvider provider) throws IOException {
gen.writeStartObject();
gen.writeStringField("name", value.getName());
// we delegate the File list serialization to its default serializer
provider.defaultSerializeField("files", value.getFiles(), gen);
gen.writeEndObject();
}
}

View File

@ -0,0 +1,166 @@
package com.baeldung.jackson.serialization.custom.serializer;
import static org.junit.Assert.assertTrue;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.io.IOException;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
import com.baeldung.jackson.entities.File;
import com.baeldung.jackson.entities.Folder;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
public class CallingDefaultSerializerUnitTest {
private ObjectMapper mapper;
private Folder mockFolder;
private TypeReference<HashMap<String, Object>> mapType;
@Before
public void setup() {
mapType = new TypeReference<HashMap<String, Object>>() {
};
mapper = new ObjectMapper();
mockFolder = new Folder();
mockFolder.setId(1L);
mockFolder.setName("Root Folder");
mockFolder.setOwner("root");
mockFolder.setCreated(Date.from(Instant.now().minusSeconds(60)));
mockFolder.setModified(Date.from(Instant.now().minusSeconds(30)));
mockFolder.setLastAccess(Date.from(Instant.now()));
File file1 = new File();
file1.setId(1L);
file1.setName("File 1");
File file2 = new File();
file2.setId(2L);
file2.setName("File 2");
List<File> files = new ArrayList<>();
files.add(file1);
files.add(file2);
mockFolder.setFiles(files);
}
@Test
public void givenFolder_whenSerialized_onlyNameAndFilesFieldsSerialized() throws IOException {
SimpleModule module = new SimpleModule();
module.addSerializer(new FolderSerializer());
mapper.registerModule(module);
String json = mapper.writeValueAsString(mockFolder);
HashMap<String, Object> actual = mapper.readValue(json, mapType);
assertTrue(actual.containsKey("name"));
assertTrue(actual.containsKey("files"));
assertEquals(mockFolder.getName(), actual.get("name"));
List actualFiles = (List) actual.get("files");
assertEquals(mockFolder.getFiles().size(), actualFiles.size());
}
@Test
public void givenFolder_whenSerializedWithSerializerProvider_onlyNameAndFilesFieldsSerialized() throws IOException {
SimpleModule module = new SimpleModule();
module.addSerializer(new FolderSerializerWithSerializerProvider());
mapper.registerModule(module);
String json = mapper.writeValueAsString(mockFolder);
HashMap<String, Object> actual = mapper.readValue(json, mapType);
assertTrue(actual.containsKey("name"));
assertTrue(actual.containsKey("files"));
assertEquals(mockFolder.getName(), actual.get("name"));
List actualFiles = (List) actual.get("files");
assertEquals(mockFolder.getFiles().size(), actualFiles.size());
}
@Test
public void givenFolder_whenSerializedWithInternalObjectMapper_onlyNameAndFilesFieldsSerialized() throws IOException {
SimpleModule module = new SimpleModule();
module.addSerializer(new FolderSerializerWithInternalObjectMapper());
mapper.registerModule(module);
String json = mapper.writeValueAsString(mockFolder);
HashMap<String, Object> actual = mapper.readValue(json, mapType);
assertTrue(actual.containsKey("name"));
assertTrue(actual.containsKey("files"));
assertEquals(mockFolder.getName(), actual.get("name"));
List actualFiles = (List) actual.get("files");
assertEquals(mockFolder.getFiles().size(), actualFiles.size());
}
@Test(expected = StackOverflowError.class)
public void givenFolder_whenSerializedWithCallingOwnSerializer_exceptionOccured() throws IOException {
SimpleModule module = new SimpleModule();
module.addSerializer(new FolderSerializerWithCallingOwnSerializer());
mapper.registerModule(module);
mapper.writeValueAsString(mockFolder);
}
@Test
public void givenFolder_whenSerializedWithDefaultSerializerStored_NameAndFilesAndDetailsFieldsSerialized() throws IOException {
SimpleModule module = new SimpleModule();
module.setSerializerModifier(new FolderBeanSerializerModifier());
mapper.registerModule(module);
String json = mapper.writeValueAsString(mockFolder);
HashMap<String, Object> actual = mapper.readValue(json, mapType);
assertTrue(actual.containsKey("name"));
assertTrue(actual.containsKey("files"));
assertEquals(mockFolder.getName(), actual.get("name"));
List actualFiles = (List) actual.get("files");
assertEquals(mockFolder.getFiles().size(), actualFiles.size());
Map actualDetails = (Map) actual.get("details");
assertTrue(actualDetails.containsKey("id"));
assertTrue(actualDetails.containsKey("name"));
assertTrue(actualDetails.containsKey("owner"));
assertTrue(actualDetails.containsKey("created"));
assertTrue(actualDetails.containsKey("modified"));
assertTrue(actualDetails.containsKey("lastAccess"));
assertEquals(mockFolder.getId().longValue(), ((Number)actualDetails.get("id")).longValue());
assertEquals(mockFolder.getName(), actualDetails.get("name"));
assertEquals(mockFolder.getOwner(), actualDetails.get("owner"));
assertEquals(mockFolder.getCreated(), new Date((long) actualDetails.get("created")));
assertEquals(mockFolder.getModified(), new Date((long) actualDetails.get("modified")));
assertEquals(mockFolder.getLastAccess(), new Date((long) actualDetails.get("lastAccess")));
}
}