Jackson: how to prevent field serialization (while keeping deserialization)
I am not sure whether it is elegant solution but you can use MixIn feature. You have to create new interface which could look like below:
interface FooMixIn {
@JsonIgnore
String getBar();
}
Assume that your POJO
looks like this:
class Foo {
private final String bar = null;
public String getBar() {
return bar;
}
@Override
public String toString() {
return bar;
}
}
Now you have to tell Jackson
that you want to ignore this property:
String json = "{\"bar\":\"Value\"}";
System.out.println(json);
ObjectMapper deserializeMapper = new ObjectMapper();
deserializeMapper.addMixInAnnotations(Foo.class, FooMixIn.class);
System.out.println(deserializeMapper.readValue(json, Foo.class));
Above example prints:
{"bar":"Value"}
null
Without deserializeMapper.addMixInAnnotations(Foo.class, FooMixIn.class);
line above program prints:
{"bar":"Value"}
Value
EDIT 1
If you want to achieve result like you showed you have to create two ObjectMapper
s and customize them. See below example:
String json = "{\"bar\":\"Value\"}";
ObjectMapper deserializerMapper = new ObjectMapper();
Foo foo = deserializerMapper.readValue(json, Foo.class);
System.out.println("Foo object: " + foo);
ObjectMapper serializerMapper = new ObjectMapper();
serializerMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
serializerMapper.addMixInAnnotations(Foo.class, FooMixIn.class);
System.out.println("JSON: " + serializerMapper.writeValueAsString(foo));
For serialization you have to use one instance and for deserialization you have to use another instance.
Disable field serialization per ObjectMapper
When you use common model classes on two sides: client and server you can register all differences using com.fasterxml.jackson.databind.Module
class and its implementations. In case, some Jackson
configuration should be available only on one side you can move it to MixIn classes/interfaces and register only on given side.
Simple example:
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.IOException;
public class ClientServerApp {
public static void main(String[] args) throws IOException {
// Client side
ObjectMapper clientMapper = JsonMapper.builder().build();
// create payload on client side
MyClass instance = new MyClass(1, "fieldValue");
String payload = clientMapper.writeValueAsString(instance);
// send to server
System.out.println("Send: " + payload);
// ..
// Server side
ObjectMapper serverMapper = JsonMapper.builder()
.addModule(new ServerModule())
.build();
MyClass deserialized = serverMapper.readValue(payload, MyClass.class);
System.out.println("Deserialized: " + deserialized);
System.out.println("Payload on server side: " + serverMapper.writeValueAsString(deserialized));
}
}
class ServerModule extends SimpleModule {
public ServerModule() {
setMixInAnnotation(MyClass.class, MyClassServerMixIn.class);
// add other configuration
}
}
@Data
@AllArgsConstructor
@NoArgsConstructor
class MyClass {
private int id;
private String field;
}
interface MyClassServerMixIn {
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
String getField();
}
Above code prints:
Send: {"id":1,"field":"fieldValue"}
Deserialized: MyClass(id=1, field=fieldValue)
Payload on server side: {"id":1}
As you can notice, only ObjectMapper
on client side can serialise field
property.
Is there any way to prevent field from deserialization in jackson?
The "trick" is to combine the @JsonProperty and @JsonIgnore on the setters and getters, like in the following example
public class SerializeDemo{
@JsonIgnore
private String serializeOnly;
@JsonProperty("serializeOnly")
public String getSerializeOnly() {
return serializeOnly;
}
@JsonIgnore
public void setSerializeOnly(String serializeOnly) {
this.serializeOnly= serializeOnly;
}
}
Dynamically prevent certain fields from being serialized with Jackson's PropertyFilter
I found the solution, and it's exactly what I was looking for. The secret is the method BeanPropertyWriter#serializeAsOmittedField(Object, JsonGenerator, SerializerProvider)
. This does exactly what is impossible to do inside of a JsonSerializer - it completely removed the field from the output.
Here's an example of this DynamicPropertyFilter:
public class DynamicPropertyFilter implements PropertyFilter {
public void serializeAsField(Object pojo, JsonGenerator jgen, SerializerProvider prov, PropertyWriter writer) throws Exception {
if (writer instanceof BeanPropertyWriter) {
BeanPropertyWriter bWriter = (BeanPropertyWriter) writer;
String fieldName = bWriter.getFullName().getSimpleName();
Field field = pojo.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
Object object = field.get(pojo);
if (Double.class.isInstance(object) && (double) object == 0.0) {
// Remove all double fields that are equal to 0.0
bWriter.serializeAsOmittedField(pojo, jgen, prov);
return;
} else if (Boolean.class.isInstance(object)) {
// Change all boolean fields to 1 and 0 instead of true and false
prov.defaultSerializeField(fieldName, (boolean) object ? 1 : 0, jgen);
return;
}
}
// Serialize field as normal if property is not filtered
writer.serializeAsField(pojo, jgen, prov);
}
public void serializeAsElement(Object elementValue, JsonGenerator jgen, SerializerProvider prov, PropertyWriter writer) throws Exception {
writer.serializeAsField(elementValue, jgen, prov);
}
public void depositSchemaProperty(PropertyWriter writer, JsonObjectFormatVisitor objectVisitor, SerializerProvider provider) throws JsonMappingException {
writer.depositSchemaProperty(objectVisitor, provider);
}
@Deprecated
public void depositSchemaProperty(PropertyWriter writer, ObjectNode propertiesNode, SerializerProvider provider) throws JsonMappingException {
writer.depositSchemaProperty(propertiesNode, provider);
}
}
Not only can I filter fields, which is primarily what I wanted, but I can also change them (as seen in the boolean example). This eliminates the need for both a PropertyFilter and a JsonSerializer.
Jackson: Prevent serialization of json string obtained by serializing a hashmap
Add the @JsonRawValue
annotation to the body
property. This makes Jackson treat the contents of the property as a literal JSON value, that should not be processed.
Be aware that Jackson doesn't do any validation of the field's contents, which makes it dangerously easy to produce invalid JSON.
Jackson JSON Serialization without field name
From the wiki page it sounds like the @JsonUnwrapped
annotation should do what you want.
@JsonUnwrapped: property annotation used to define that value should be "unwrapped" when serialized (and wrapped again when deserializing), resulting in flattening of data structure, compared to POJO structure.
The Javadoc for the class also has an example that looks appropriate.
Prevent custom serialization of specific field
It's possible to get the name of currently serialized field by implementing ContextualSerializer
. The default serialization is available through SerializerProvider
. Try rewriting the serializer like this:
class DateSerializer extends JsonSerializer<Date> implements ContextualSerializer {
private boolean doCustom;
DateSerializer() {}
private DateSerializer(boolean doCustom) { this.doCustom = doCustom; }
@Override
public void serialize(Date value, JsonGenerator gen, SerializerProvider provider) throws IOException {
if (doCustom) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
String date = sdf.format(value);
gen.writeString(date);
} else {
provider.defaultSerializeDateValue(value, gen);
}
}
@Override
public JsonSerializer<Date> createContextual(SerializerProvider config, BeanProperty property) {
boolean doCustom = property == null || !"dateToBeDefaultSerialized".equals(property.getName());
return new DateSerializer(doCustom);
}
}
Jackson JSON serializer: enable or disable serialisation of certain field in runtime?
Quite a few ways, from simple JSON Views to @JsonFilter
, explained at "Every day Jackson usage, part 3: Filtering properties" (and its followup, "Advanced filtering with Jackson, Json Filters")
Related Topics
How to Find Out What Keystore My Jvm Is Using
How to Get a Unicode Character's Code
How to Write an Arraylist of Strings into a Text File
Spring Boot Redirect Http to Https
What's the Difference Between Instance Method Reference Types in Java 8
How to View Tomcat Log Files in Eclipse
Preparedstatement with Statement.Return_Generated_Keys
How to Manually Set an Authenticated User in Spring Security/Springmvc
How to Get Current Working Directory in Java
Error Message "Unreported Exception Java.Io.Ioexception; Must Be Caught or Declared to Be Thrown"
Encrypt and Decrypt with Aes and Base64 Encoding