Add source code for article BAEL-2463 (#7543)
This commit is contained in:
parent
32127cc5b5
commit
9cb93861d9
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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")));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user