Jackson: How to Prevent Field Serialization

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 ObjectMappers 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



Leave a reply



Submit