I need to create a json from an Object. The Object contains a List member variable of type Name. Name is a class which contains an enum NameType. below are the class:
public final class Person { private final List<Name> names; }
public class Name {
private final String first;
private final String last;
private final String middle;
private final NameType type;
}
public enum NameType {
X,
Y,
Z
}
The json that is produced for class Person should not include Name for which NameType is Y and Z. Below is the simple way in which I try to generate the json:
Map<String, Object> personMap = mapper.readValue(person!=null ? mapper.writeValueAsString(person) : "{}", typeReference);
I need to remove the key "names" from personMap. I have searched a few ways to remove it before serialization, but that hasn't worked for me. I followed this tutorial:
Thanks in Advance!!
CodePudding user response:
Disclaimer: I never used Jackson before, this was my first contact. I was just looking for a little puzzle to solve while drinking my morning tea, which also enables me to learn something. So I am not sure if there are better or more elegant ways of doing this.
In order to present an MCVE which everyone can easily compile and execute, here are my more complete versions (including getters) of your example classes:
package de.scrum_master.stackoverflow.q71358052;
public enum NameType {
REAL,
ARTIST,
ONLINE
}
package de.scrum_master.stackoverflow.q71358052;
public class Name {
private final String first;
private final String last;
private final String middle;
private final NameType type;
public Name(String first, String last, String middle, NameType type) {
this.first = first;
this.last = last;
this.middle = middle;
this.type = type;
}
public String getFirst() {
return first;
}
public String getLast() {
return last;
}
public String getMiddle() {
return middle;
}
public NameType getType() {
return type;
}
}
package de.scrum_master.stackoverflow.q71358052;
import java.util.List;
public final class Person {
private final List<Name> names;
public Person(List<Name> names) {
this.names = names;
}
public List<Name> getNames() {
return names;
}
}
As described for a similar case in this tutorial, we can use a custom JsonSerializer<Name>
in combination with a BeanSerializerModifier
, registering them on the ObjectMapper
in a SimpleModule
:
package de.scrum_master.stackoverflow.q71358052;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
public class NameSerializer extends JsonSerializer<Name> {
private final JsonSerializer<Object> defaultSerializer;
public NameSerializer(JsonSerializer<Object> serializer) {
defaultSerializer = serializer;
}
@Override
public void serialize(Name value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
if (value.getType() != NameType.REAL)
return;
defaultSerializer.serialize(value, gen, serializers);
}
@Override
public boolean isEmpty(SerializerProvider provider, Name value) {
return value == null || value.getType() != NameType.REAL;
}
}
package de.scrum_master.stackoverflow.q71358052;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationConfig;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.BeanSerializerModifier;
import java.util.List;
public class JacksonDemo {
public static void main(String[] args) throws JsonProcessingException {
Person person = new Person(List.of(
new Name("Edward", "Robinson", "G.", NameType.ARTIST),
new Name("Emanuel", "Goldenberg", null, NameType.REAL),
new Name("Эмануэль", "Голденберг", null, NameType.REAL),
new Name("Eddie", "The Gangster", null, NameType.ONLINE)
));
ObjectMapper objectMapper = getObjectMapper();
String personJson = objectMapper.writeValueAsString(person);
System.out.println(personJson.contains("ARTIST")); // false
System.out.println(personJson.contains("ONLINE")); // false
System.out.println(personJson.contains("Goldenberg")); // true
System.out.println(personJson.contains("Голденберг")); // true
System.out.println(personJson);
}
private static ObjectMapper getObjectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
objectMapper.registerModule(
new SimpleModule() {
@Override
public void setupModule(SetupContext context) {
super.setupModule(context);
context.addBeanSerializerModifier(
new BeanSerializerModifier() {
@Override
public JsonSerializer<?> modifySerializer(SerializationConfig config, BeanDescription beanDesc, JsonSerializer<?> serializer) {
if (Name.class.isAssignableFrom(beanDesc.getBeanClass()))
return new NameSerializer((JsonSerializer<Object>) serializer);
return serializer;
}
}
);
}
}
);
return objectMapper;
}
}
The console log should be:
false
false
true
true
{"names":[{"first":"Emanuel","last":"Goldenberg","type":"REAL"},{"first":"Эмануэль","last":"Голденберг","type":"REAL"}]}
Oh, by the way and just in case not everybody knows who Edward G. Robinson was...