Ignore Fields from Java Object Dynamically While Sending as JSON from Spring MVC

Ignore fields from Java object dynamically while sending as JSON from Spring MVC

Add the @JsonIgnoreProperties("fieldname") annotation to your POJO.

Or you can use @JsonIgnore before the name of the field you want to ignore while deserializing JSON. Example:

@JsonIgnore
@JsonProperty(value = "user_password")
public String getUserPassword() {
return userPassword;
}

GitHub example

How to dynamically ignore a property on Jackson serialization

I've put together three approaches for performing dynamic filtering in Jackson. One of them must suit your needs.

Using @JsonView

You could use @JsonView:

public class Views {         
interface Simple { }
interface Detailed extends Simple { }
}
public class Foo {

@JsonView(Views.Simple.class)
private String name;

@JsonView(Views.Detailed.class)
private String details;

// Getters and setters
}
@RequestMapping("/foo")
@JsonView(Views.Detailed.class)
public Foo getFoo() {
Foo foo = new Foo();
return foo;
}

Alternatively you can set the view dynamically with MappingJacksonValue.

@RequestMapping("/foo")
public MappingJacksonValue getFoo() {
Foo foo = new Foo();
MappingJacksonValue result = new MappingJacksonValue(foo);
result.setSerializationView(Views.Detailed.class);
return result;
}

Using a BeanSerializerModifier

You could extend BeanSerializerModifier and then override the changeProperties() method. It allows you to add, remove or replace any of properties for serialization, according to your needs:

public class CustomSerializerModifier extends BeanSerializerModifier {

@Override
public List<BeanPropertyWriter> changeProperties(SerializationConfig config,
BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {

// In this method you can add, remove or replace any of passed properties

return beanProperties;
}
}

Then register the serializer as a module in your ObjectMapper:

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new SimpleModule() {

@Override
public void setupModule(SetupContext context) {
super.setupModule(context);
context.addBeanSerializerModifier(new CustomSerializerModifier());
}
});

Check examples here and here.

Using @JsonFilter with a SimpleBeanPropertyFilter

Another approach involves @JsonFilter:

@JsonFilter("customPropertyFilter")
public class Foo {

private String name;
private String details;

// Getters and setters
}

Extend SimpleBeanPropertyFilter and override the serializeAsField() method according to your needs:

public class CustomPropertyFilter extends SimpleBeanPropertyFilter {

@Override
public void serializeAsField(Object pojo, JsonGenerator jgen,
SerializerProvider provider,
PropertyWriter writer) throws Exception {

// Serialize a field
// writer.serializeAsField(pojo, jgen, provider, writer);

// Omit a field from serialization
// writer.serializeAsOmittedField(pojo, jgen, provider);
}
}

Then register the filter in your ObjectMapper:

FilterProvider filterProvider = new SimpleFilterProvider()
.addFilter("customPropertyFilter", new CustomPropertyFilter());

ObjectMapper mapper = new ObjectMapper();
mapper.setFilterProvider(filterProvider);

If you want to make your filter "global", that is, to be applied to all beans, you can create a mix-in class and annotate it with @JsonFilter("customPropertyFilter"):

@JsonFilter("customPropertyFilter")
public class CustomPropertyFilterMixIn {

}

Then bind the mix-in class to Object:

mapper.addMixIn(Object.class, CustomPropertyFilterMixIn.class);

Spring and Jackson: set json ignore dynamically

I never use my Entitys for generating JSON, I think another set DTO classes will make you happier in the long run. My DTO typically has a constructor which takes the Entity as argument (it still needs a default constructor if you plan to use it for parsing incoming JSON).

If you really want to use your Entities, I would recommend that you use MixIns, which allows you to register a MixIn class, that augments the serialization of a specific class.

Here is a link to a MixIn example I made for another answer.

Exclude fields from Java object using Spring

I fully agree with Tod Harter that it's better and easier to use DTOs.

That being said, I don't know how you've tried to use the @JSonView annotation. I use it in some of my DTOs. One way of getting the @JsonView annotation to work is to first create an interface. i.e.:

public interface Views {
public static interface Simple {
}

public static interface Detailed extends Simple {
}

...
}

Then you need to reference the views above the fields that you want to apply them to like this:

@JsonView(Views.Simple.class)
private String someField;

@JsonView(Views.Detailed.class)
private String anotherField;

...

After that you need to convert your entity object to a MappingJacksonValue like this:

...
var responseObject = new MappingJacksonValue(obj);
responseObject.setSerializationView(Views.Simple.class);
...

This is one of the ways to make the @JsonView annotations work as expected. however, it is much easier (and better) to just use DTOs and convert your entity to the appropriate response DTO you've created. You can make as many DTOs as you want. It's also a good idea to use DTOs to map request bodies. That way you can easily control which fields are allowed in request bodies for i.e. POST/PUT/PATCH requests. Take a look at the ModelMapper and/or ObjectMapper classes. Those can be used to convert entities to and from DTOs.



Related Topics



Leave a reply



Submit