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

18

152

I have model class like this, for hibernate

@Entity
@Table(name = "user", catalog = "userdb")
@JsonIgnoreProperties(ignoreUnknown = true)
public class User implements java.io.Serializable {

    private Integer userId;
    private String userName;
    private String emailId;
    private String encryptedPwd;
    private String createdBy;
    private String updatedBy;

    @Id
    @GeneratedValue(strategy = IDENTITY)
    @Column(name = "UserId", unique = true, nullable = false)
    public Integer getUserId() {
        return this.userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }

    @Column(name = "UserName", length = 100)
    public String getUserName() {
        return this.userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    @Column(name = "EmailId", nullable = false, length = 45)
    public String getEmailId() {
        return this.emailId;
    }

    public void setEmailId(String emailId) {
        this.emailId = emailId;
    }

    @Column(name = "EncryptedPwd", length = 100)
    public String getEncryptedPwd() {
        return this.encryptedPwd;
    }

    public void setEncryptedPwd(String encryptedPwd) {
        this.encryptedPwd = encryptedPwd;
    }

    public void setCreatedBy(String createdBy) {
        this.createdBy = createdBy;
    }

    @Column(name = "UpdatedBy", length = 100)
    public String getUpdatedBy() {
        return this.updatedBy;
    }

    public void setUpdatedBy(String updatedBy) {
        this.updatedBy = updatedBy;
    }
}

In Spring MVC controller, using DAO, I am able to get the object. and returning as JSON Object.

@Controller
public class UserController {

    @Autowired
    private UserService userService;

    @RequestMapping(value = "/getUser/{userId}", method = RequestMethod.GET)
    @ResponseBody
    public User getUser(@PathVariable Integer userId) throws Exception {

        User user = userService.get(userId);
        user.setCreatedBy(null);
        user.setUpdatedBy(null);
        return user;
    }
}

View part is done using AngularJS, so it will get JSON like this

{
  "userId" :2,
  "userName" : "john",
  "emailId" : "[email protected]",
  "encryptedPwd" : "Co7Fwd1fXYk=",
  "createdBy" : null,
  "updatedBy" : null
}

If I don't want to set encrypted Password, I will set that field also as null.

But I don't want like this, I dont want to send all fields to client side. If I dont want password, updatedby, createdby fields to send, My result JSON should be like

{
  "userId" :2,
  "userName" : "john",
  "emailId" : "[email protected]"
}

The list of fields which I don't want to send to client coming from other database table. So it will change based on the user who is logged in. How can I do that?

I hope You got my question.

Southwesterly answered 16/4, 2014 at 6:5 Comment(4)
What would you say about this answer? https://mcmap.net/q/138203/-spring-rest-controller-return-specific-fieldsBailment
this information may be helpful #12505641Pelias
I answered here Easy way to filter fields dynamicallyStucco
To dynamically ignore the field in json response, before you send back your response, try setting that field to null i.e entityClass.setFieldToIgnore(null). The spring-mvc is by default set to ignore null values when deserializing, or you can configure it manuallyBlacken
C
189

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

Carberry answered 16/4, 2014 at 6:12 Comment(19)
Can I do it dynamically? Not in POJO? Can I do it in my Controller class?Southwesterly
@iProgrammer : here is a similar as you want :#8180486Nunhood
@iProgrammer : very impressive answer here #13764780Nunhood
remark:@JsonIgnore is com.fasterxml.jackson.annotation.JsonIgnore not org.codehaus.jackson.annotate.JsonIgnore.Chilt
That ignores both while reading from request and while sending response. I want to ignore only while sending response because i need that property from the request object. Any ideas?Trichomonad
Hello @zulkarnainshah: you can use json serializer then.Nunhood
@user3145373ツ. I think I need to set the JSONIgnore on the getter method of that field and remove it from the field itself.Trichomonad
@zulkarnainshah: refer #12505641 for more detailsNunhood
@user3145373ツ Ya the JSONIgnore needs to be only on top of the getter method. Thanks !Trichomonad
I guess JsonFilter annotation is what you need.Childbirth
@user3145373ツ this does not work for inner class. what should be done to make it work for attributes/fields in the inner class ?Argumentum
@Argumentum you need to use same annotation in inner class. If you do not want to whole inner class then you need to add annotation in parent one.Nunhood
@user3145373ツ i want few fields of the inner class but not all. adding annotation on the fields of the inner class which i dont need does not work.Argumentum
@Argumentum Annotation work at any place, parent-child it does not matter.Nunhood
It is not the answer for THAT question. Why the @Southwesterly accepted it I couldn't understand.Kilauea
@Olkunmustafa: Can you please explain what's wrong in this and what actually -iCode wants? If something is wrong then happy to correct it.Nunhood
@user3145373ツ Because -iCode is asking to change response dynamically not in POJO. Already he commented about it but the answer accepted I couldn't understand. Correct answer should be this one => https://mcmap.net/q/136874/-ignore-fields-from-java-object-dynamically-while-sending-as-json-from-spring-mvcKilauea
Another solution is to use a Data Transfer Object (DTO) which allows to only send fields that your client needs. This object will only have userId, userName and emailId as attributes.Eulalia
But to not to add this attribute in serialization and de-serialization we and define '@JsonIgnore' at data-member level: @JsonIgnore private String userPassword;Definite
R
54

Can I do it dynamically?

Create view class:

public class View {
    static class Public { }
    static class ExtendedPublic extends Public { }
    static class Internal extends ExtendedPublic { }
}

Annotate you model

@Document
public class User {

    @Id
    @JsonView(View.Public.class)
    private String id;

    @JsonView(View.Internal.class)
    private String email;

    @JsonView(View.Public.class)
    private String name;

    @JsonView(View.Public.class)
    private Instant createdAt = Instant.now();
    // getters/setters
}

Specify the view class in your controller

@RequestMapping("/user/{email}")
public class UserController {

    private final UserRepository userRepository;

    @Autowired
    UserController(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    @RequestMapping(method = RequestMethod.GET)
    @JsonView(View.Internal.class)
    public @ResponseBody Optional<User> get(@PathVariable String email) {
        return userRepository.findByEmail(email);
    }

}

Data example:

{"id":"5aa2496df863482dc4da2067","name":"test","createdAt":"2018-03-10T09:35:31.050353800Z"}

UPD: keep in mind that it's not best practice to use entity in response. Better use different DTO for each case and fill them using modelmapper

Retardant answered 10/3, 2018 at 9:36 Comment(3)
This is a fantastic and minimalistic answer! I wanted to return as a JSON just only few fields from a @Configuration annotated component and skipping all the internal fields that are automatically included. Thanks a lot!Dolli
This should be the accepted solution. Really helped. Thanks @RetardantSpirt
Don't forget to add spring.jackson.mapper.default-view-inclusion=true to cascade to child objects, see here https://mcmap.net/q/138207/-spring-json-serialization-with-jsonview-return-empty-objects-for-associationsHutchens
A
41

I know I'm a bit late to the party, but I actually ran into this as well a few months back. All of the available solutions weren't very appealing to me (mixins? ugh!), so I ended up creating a new library to make this process cleaner. It's available here if anyone would like to try it out: https://github.com/monitorjbl/spring-json-view.

The basic usage is pretty simple, you use the JsonView object in your controller methods like so:

import com.monitorjbl.json.JsonView;
import static com.monitorjbl.json.Match.match;

@RequestMapping(method = RequestMethod.GET, value = "/myObject")
@ResponseBody
public void getMyObjects() {
    //get a list of the objects
    List<MyObject> list = myObjectService.list();

    //exclude expensive field
    JsonView.with(list).onClass(MyObject.class, match().exclude("contains"));
}

You can also use it outside of Spring:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import static com.monitorjbl.json.Match.match;

ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addSerializer(JsonView.class, new JsonViewSerializer());
mapper.registerModule(module);

mapper.writeValueAsString(JsonView.with(list)
      .onClass(MyObject.class, match()
        .exclude("contains"))
      .onClass(MySmallObject.class, match()
        .exclude("id"));
Adenectomy answered 7/2, 2015 at 23:7 Comment(5)
Thank you! This was the way to go for me. I needed custom JSON views with the same objects in different locations and @JsonIgnore just wouldn't work. This library made it dead simple get done.Potter
You made my code cleaner and implementation easier. thank youKelbee
@Adenectomy : this is a bit off track, I have used json views and its solving my purpose. But I am not able to register custom serializer for java.util.Date class(no runtime/compile time error) were as for string I was able to register custom serializer.Virago
JsonView seems to be part of Jackson object mapper nowAesculapius
@Adenectomy intresting, i guess i'll try your libraryAftmost
B
23

We can do this by setting access to JsonProperty.Access.WRITE_ONLY while declaring the property.

@JsonProperty( value = "password", access = JsonProperty.Access.WRITE_ONLY)
@SerializedName("password")
private String password;
Brochure answered 9/10, 2018 at 17:58 Comment(1)
Just incase someone comes looking, I used this to ignore a property sent in the request, but still have in the response. Other solutions like @JsonIgnore ignores the property in both the request and responseTress
C
22

Yes, you can specify which fields are serialized as JSON response and which to ignore. This is what you need to do to implement Dynamically ignore properties.

1) First, you need to add @JsonFilter from com.fasterxml.jackson.annotation.JsonFilter on your entity class as.

import com.fasterxml.jackson.annotation.JsonFilter;

@JsonFilter("SomeBeanFilter")
public class SomeBean {

  private String field1;

  private String field2;

  private String field3;

  // getters/setters
}

2) Then in your controller, you have to add create the MappingJacksonValue object and set filters on it and in the end, you have to return this object.

import java.util.Arrays;
import java.util.List;

import org.springframework.http.converter.json.MappingJacksonValue;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import com.fasterxml.jackson.databind.ser.FilterProvider;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;

@RestController
public class FilteringController {

  // Here i want to ignore all properties except field1,field2.
  @GetMapping("/ignoreProperties")
  public MappingJacksonValue retrieveSomeBean() {
    SomeBean someBean = new SomeBean("value1", "value2", "value3");

    SimpleBeanPropertyFilter filter = SimpleBeanPropertyFilter.filterOutAllExcept("field1", "field2");

    FilterProvider filters = new SimpleFilterProvider().addFilter("SomeBeanFilter", filter);

    MappingJacksonValue mapping = new MappingJacksonValue(someBean);

    mapping.setFilters(filters);

    return mapping;
  }
}

This is what you will get in response:

{
  field1:"value1",
  field2:"value2"
}

instead of this:

{
  field1:"value1",
  field2:"value2",
  field3:"value3"
}

Here you can see it ignores other properties(field3 in this case) in response except for property field1 and field2.

Hope this helps.

Christiansen answered 23/8, 2018 at 16:44 Comment(1)
@Shafqat Man, thank you so much, you are my savior. Spent almost a day trying to find out this kind of functionality. This solution is so elegant and simple? and does exactly what was requested. Should be marked as the right answer.Expurgatory
C
16

Add @JsonInclude(JsonInclude.Include.NON_NULL) (forces Jackson to serialize null values) to the class as well as @JsonIgnore to the password field.

You could of course set @JsonIgnore on createdBy and updatedBy as well if you always want to ignore then and not just in this specific case.

UPDATE

In the event that you do not want to add the annotation to the POJO itself, a great option is Jackson's Mixin Annotations. Check out the documentation

Chlordane answered 16/4, 2014 at 6:10 Comment(3)
Can I do it dynamically? Not in POJO? Can I do it in my Controller class?Southwesterly
Do you mean that you don't want to add the annotations to the POJO?Chlordane
Because Sometimes I may want to send all the fields to client side. Sometimes few fields. The fields which I should send to client side is getting from database in the controller class only. After that only I need to set which fields should ignore.Southwesterly
H
10

I've solved using only @JsonIgnore like @kryger has suggested. So your getter will become:

@JsonIgnore
public String getEncryptedPwd() {
    return this.encryptedPwd;
}

You can set @JsonIgnore of course on field, setter or getter like described here.

And, if you want to protect encrypted password only on serialization side (e.g. when you need to login your users), add this @JsonProperty annotation to your field:

@JsonProperty(access = Access.WRITE_ONLY)
private String encryptedPwd;

More info here.

Hoggish answered 18/6, 2019 at 13:26 Comment(0)
T
6

If I were you and wanted to do so, I wouldn't use my User entity in Controller layer.Instead I create and use UserDto (Data transfer object) to communicate with business(Service) layer and Controller. You can use Apache BeanUtils(copyProperties method) to copy data from User entity to UserDto.

Thora answered 14/4, 2016 at 12:3 Comment(0)
Z
5

I have created a JsonUtil which can be used to ignore fields at runtime while giving a response.

Example Usage : First argument should be any POJO class (Student) and ignoreFields is comma seperated fields you want to ignore in response.

 Student st = new Student();
 createJsonIgnoreFields(st,"firstname,age");

import java.util.logging.Logger;

import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.ObjectWriter;
import org.codehaus.jackson.map.ser.FilterProvider;
import org.codehaus.jackson.map.ser.impl.SimpleBeanPropertyFilter;
import org.codehaus.jackson.map.ser.impl.SimpleFilterProvider;

public class JsonUtil {

  public static String createJsonIgnoreFields(Object object, String ignoreFields) {
     try {
         ObjectMapper mapper = new ObjectMapper();
         mapper.getSerializationConfig().addMixInAnnotations(Object.class, JsonPropertyFilterMixIn.class);
         String[] ignoreFieldsArray = ignoreFields.split(",");
         FilterProvider filters = new SimpleFilterProvider()
             .addFilter("filter properties by field names",
                 SimpleBeanPropertyFilter.serializeAllExcept(ignoreFieldsArray));
         ObjectWriter writer = mapper.writer().withFilters(filters);
         return writer.writeValueAsString(object);
     } catch (Exception e) {
         //handle exception here
     }
     return "";
   }

   public static String createJson(Object object) {
        try {
         ObjectMapper mapper = new ObjectMapper();
         ObjectWriter writer = mapper.writer().withDefaultPrettyPrinter();
         return writer.writeValueAsString(object);
        }catch (Exception e) {
         //handle exception here
        }
        return "";
   }
 }    
Zibet answered 17/4, 2018 at 18:56 Comment(0)
C
1

I've found a solution for me with Spring and jackson

First specify the filter name in the entity

@Entity
@Table(name = "SECTEUR")
@JsonFilter(ModelJsonFilters.SECTEUR_FILTER)
public class Secteur implements Serializable {

/** Serial UID */
private static final long serialVersionUID = 5697181222899184767L;

/**
 * Unique ID
 */
@Id
@JsonView(View.SecteurWithoutChildrens.class)
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;

@JsonView(View.SecteurWithoutChildrens.class)
@Column(name = "code", nullable = false, length = 35)
private String code;

/**
 * Identifiant du secteur parent
 */
@JsonView(View.SecteurWithoutChildrens.class)
@Column(name = "id_parent")
private Long idParent;

@OneToMany(fetch = FetchType.LAZY)
@JoinColumn(name = "id_parent")
private List<Secteur> secteursEnfants = new ArrayList<>(0);

}

Then you can see the constants filters names class with the default FilterProvider used in spring configuration

public class ModelJsonFilters {

public final static String SECTEUR_FILTER = "SecteurFilter";
public final static String APPLICATION_FILTER = "ApplicationFilter";
public final static String SERVICE_FILTER = "ServiceFilter";
public final static String UTILISATEUR_FILTER = "UtilisateurFilter";

public static SimpleFilterProvider getDefaultFilters() {
    SimpleBeanPropertyFilter theFilter = SimpleBeanPropertyFilter.serializeAll();
    return new SimpleFilterProvider().setDefaultFilter(theFilter);
}

}

Spring configuration :

@EnableWebMvc
@Configuration
@ComponentScan(basePackages = "fr.sodebo")

public class ApiRootConfiguration extends WebMvcConfigurerAdapter {

@Autowired
private EntityManagerFactory entityManagerFactory;


/**
 * config qui permet d'éviter les "Lazy loading Error" au moment de la
 * conversion json par jackson pour les retours des services REST<br>
 * on permet à jackson d'acceder à sessionFactory pour charger ce dont il a
 * besoin
 */
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {

    super.configureMessageConverters(converters);
    MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
    ObjectMapper mapper = new ObjectMapper();

    // config d'hibernate pour la conversion json
    mapper.registerModule(getConfiguredHibernateModule());//

    // inscrit les filtres json
    subscribeFiltersInMapper(mapper);

    // config du comportement de json views
    mapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, false);

    converter.setObjectMapper(mapper);
    converters.add(converter);
}

/**
 * config d'hibernate pour la conversion json
 * 
 * @return Hibernate5Module
 */
private Hibernate5Module getConfiguredHibernateModule() {
    SessionFactory sessionFactory = entityManagerFactory.unwrap(SessionFactory.class);
    Hibernate5Module module = new Hibernate5Module(sessionFactory);
    module.configure(Hibernate5Module.Feature.FORCE_LAZY_LOADING, true);

    return module;

}

/**
 * inscrit les filtres json
 * 
 * @param mapper
 */
private void subscribeFiltersInMapper(ObjectMapper mapper) {

    mapper.setFilterProvider(ModelJsonFilters.getDefaultFilters());

}

}

Endly I can specify a specific filter in restConstoller when i need....

@RequestMapping(value = "/{id}/droits/", method = RequestMethod.GET)
public MappingJacksonValue getListDroits(@PathVariable long id) {

    LOGGER.debug("Get all droits of user with id {}", id);

    List<Droit> droits = utilisateurService.findDroitsDeUtilisateur(id);

    MappingJacksonValue value;

    UtilisateurWithSecteurs utilisateurWithSecteurs = droitsUtilisateur.fillLists(droits).get(id);

    value = new MappingJacksonValue(utilisateurWithSecteurs);

    FilterProvider filters = ModelJsonFilters.getDefaultFilters().addFilter(ModelJsonFilters.SECTEUR_FILTER, SimpleBeanPropertyFilter.serializeAllExcept("secteursEnfants")).addFilter(ModelJsonFilters.APPLICATION_FILTER,
            SimpleBeanPropertyFilter.serializeAllExcept("services"));

    value.setFilters(filters);
    return value;

}
Cymbre answered 2/5, 2016 at 12:53 Comment(1)
why so complications for an easy questionBarny
D
1

Place @JsonIgnore on the field or its getter, or create a custom dto

@JsonIgnore
private String encryptedPwd;

or as mentioned above by ceekay annotate it with @JsonProperty where access attribute is set to write only

@JsonProperty( value = "password", access = JsonProperty.Access.WRITE_ONLY)
private String encryptedPwd;
Darlenedarline answered 18/6, 2019 at 13:50 Comment(0)
C
1

Hi I have achieved dynamic filtering by using Gson library like in the below:

JsonObject jsonObj = new Gson().fromJson(mapper.writeValueAsString(sampleObject), JsonObject.class);
jsonObj.remove("someProperty");
String data = new Gson().toJson(jsonObj);
Cassel answered 18/11, 2021 at 21:15 Comment(0)
H
1

Can I do it dynamically?

Yes, you can use a combination of Jackson's PropertyFilter and mixins.

Explanation

Jackson has a PropertyFilter interface to implement a filter to ignore fields dynamically. The problem is that filter has to be defined on the DTO/POJO class using the @JsonFilter annotation.

To avoid adding a @JsonFilter on class we can use ObjectMapper's addMixIn method to "dynamically" add this annotation (and leave our DTO/POJO classes as is).

Code example

Here is my implementation of the idea provided above. We can call toJson() with two arguments: (1) object to be serialized and (2) lambda (Java's Predicate) to be used in PropertyFilter:

public class JsonService {

    public String toJson(Object object, Predicate<PropertyWriter> filter) {
        ObjectMapper mapper = new ObjectMapper();
        FilterProvider filterProvider = new SimpleFilterProvider()
                .addFilter("DynamicFilter", new DynamicFilter(filter));
        mapper.setFilterProvider(filterProvider);
        mapper.addMixIn(object.getClass(), DynamicFilterMixin.class);
        try {
            return mapper.writeValueAsString(object);
        } catch (JsonProcessingException e) {
            throw new MyException(e);
        }
    }

    private static final class DynamicFilter extends SimpleBeanPropertyFilter {

        private Predicate<PropertyWriter> filter;

        private DynamicFilter(Predicate<PropertyWriter> filter) {
            this.filter = filter;
        }

        protected boolean include(BeanPropertyWriter writer) {
            return include((PropertyWriter) writer);
        }

        protected boolean include(PropertyWriter writer) {
            return filter.test(writer);
        }
    }

    @JsonFilter("DynamicFilter")
    private interface DynamicFilterMixin {
    }

}

Now we can call toJson and filter fields during a serialization:

  1. Filtering by name
new JsonService().toJson(object, w -> !w.getName().equals("fieldNameToBeIgnored"));
  1. Filtering by annotation (on the field)
new JsonService().toJson(object, w -> w.getAnnotation(MyAnnotation.class) == null);

Unit tests

Here are the unit tests for the class above:

public class JsonServiceTest {
    
    private JsonService jsonService = new JsonService();
    
    @Test
    public void withoutFiltering() {
        MyObject object = getObject();
        String json = jsonService.toJson(object, w -> true);
        assertEquals("{\"myString\":\"stringValue\",\"myInteger\":10,\"myBoolean\":true}", json);
    }

    @Test
    public void filteredByFieldName() {
        MyObject object = getObject();
        String json = jsonService.toJson(object, w -> !w.getName().equals("myString"));
        assertEquals("{\"myInteger\":10,\"myBoolean\":true}", json);
    }

    @Test
    public void filteredByAnnotation() {
        MyObject object = getObject();
        String json = jsonService.toJson(object, w -> w.getAnnotation(Deprecated.class) == null);
        assertEquals("{\"myString\":\"stringValue\",\"myInteger\":10}", json);
    }
    
    private MyObject getObject() {
        MyObject object = new MyObject();
        object.myString = "stringValue";
        object.myInteger = 10;
        object.myBoolean = true;
        return object;
    }
    
    private static class MyObject {
        private String myString;
        private int myInteger;
        @Deprecated
        private boolean myBoolean;

        public String getMyString() {
            return myString;
        }

        public void setMyString(String myString) {
            this.myString = myString;
        }

        public int getMyInteger() {
            return myInteger;
        }

        public void setMyInteger(int myInteger) {
            this.myInteger = myInteger;
        }

        public boolean isMyBoolean() {
            return myBoolean;
        }

        public void setMyBoolean(boolean myBoolean) {
            this.myBoolean = myBoolean;
        }
    }

}
Handwork answered 27/11, 2022 at 21:45 Comment(0)
A
0

Would not creating a UserJsonResponse class and populating with the wanted fields be a cleaner solution?

Returning directly a JSON seems a great solution when you want to give all the model back. Otherwise it just gets messy.

In the future, for example you might want to have a JSON field that does not match any Model field and then you're in a bigger trouble.

Aciculum answered 15/11, 2017 at 9:35 Comment(0)
N
0

This is a clean utility tool for the above answer :

@GetMapping(value = "/my-url")
public @ResponseBody
MappingJacksonValue getMyBean() {
    List<MyBean> myBeans = Service.findAll();
    MappingJacksonValue mappingValue = MappingFilterUtils.applyFilter(myBeans, MappingFilterUtils.JsonFilterMode.EXCLUDE_FIELD_MODE, "MyFilterName", "myBiggerObject.mySmallerObject.mySmallestObject");
    return mappingValue;
}

//AND THE UTILITY CLASS
public class MappingFilterUtils {

    public enum JsonFilterMode {
        INCLUDE_FIELD_MODE, EXCLUDE_FIELD_MODE
    }
    public static MappingJacksonValue applyFilter(Object object, final JsonFilterMode mode, final String filterName, final String... fields) {
        if (fields == null || fields.length == 0) {
            throw new IllegalArgumentException("You should pass at least one field");
        }
        return applyFilter(object, mode, filterName, new HashSet<>(Arrays.asList(fields)));
    }

    public static MappingJacksonValue applyFilter(Object object, final JsonFilterMode mode, final String filterName, final Set<String> fields) {
        if (fields == null || fields.isEmpty()) {
            throw new IllegalArgumentException("You should pass at least one field");
        }

        SimpleBeanPropertyFilter filter = null;
        switch (mode) {
            case EXCLUDE_FIELD_MODE:
                filter = SimpleBeanPropertyFilter.serializeAllExcept(fields);
                break;
            case INCLUDE_FIELD_MODE:
                filter = SimpleBeanPropertyFilter.filterOutAllExcept(fields);
                break;
        }

        FilterProvider filters = new SimpleFilterProvider().addFilter(filterName, filter);
        MappingJacksonValue mapping = new MappingJacksonValue(object);
        mapping.setFilters(filters);
        return mapping;
    }
}
Nullipore answered 26/3, 2019 at 1:49 Comment(0)
O
0

To acheive dynamic filtering follow the link - https://iamvickyav.medium.com/spring-boot-dynamically-ignore-fields-while-converting-java-object-to-json-e8d642088f55

  1. Add the @JsonFilter("Filter name") annotation to the model class.

  2. Inside the controller function add the code:-

    SimpleBeanPropertyFilter simpleBeanPropertyFilter =
            SimpleBeanPropertyFilter.serializeAllExcept("id", "dob"); 
    
    FilterProvider filterProvider = new SimpleFilterProvider()
            .addFilter("Filter name", simpleBeanPropertyFilter);
    
    List<User> userList = userService.getAllUsers();
    MappingJacksonValue mappingJacksonValue = new MappingJacksonValue(userList);
    mappingJacksonValue.setFilters(filterProvider);
    
    return mappingJacksonValue;
    
  3. make sure the return type is MappingJacksonValue.

Otoscope answered 1/12, 2020 at 7:52 Comment(0)
M
0

Simply create new dto class without field password.

class UserDto {
      // ... your field without password field
}

convert your User.java into UserDto.java on response.

Millibar answered 21/9, 2023 at 1:41 Comment(0)
G
-6

In your entity class add @JsonInclude(JsonInclude.Include.NON_NULL) annotation to resolve the problem

it will look like

@Entity
@JsonInclude(JsonInclude.Include.NON_NULL)
Ghetto answered 2/10, 2017 at 13:9 Comment(1)
Totally irrelevantly answered. The purpose of the question is different while the answer is about something else. -1 for thatExpansile

© 2022 - 2024 — McMap. All rights reserved.