从Spring MVC作为JSON发送时,动态忽略Java对象中的字段

iCo*_*ode 88 java json hibernate spring-mvc

对于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;
    }
}
Run Code Online (Sandbox Code Playgroud)

在Spring MVC控制器中,使用DAO,我能够获得该对象.并作为JSON对象返回.

@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;
    }
}
Run Code Online (Sandbox Code Playgroud)

查看部分是使用AngularJS完成的,因此它将获得这样的JSON

{
  "userId" :2,
  "userName" : "john",
  "emailId" : "john@gmail.com",
  "encryptedPwd" : "Co7Fwd1fXYk=",
  "createdBy" : null,
  "updatedBy" : null
}
Run Code Online (Sandbox Code Playgroud)

如果我不想设置加密密码,我将该字段也设置为空.

但我不想这样,我不想将所有字段发送到客户端.如果我不想要密码,更新,由字段创建发送,我的结果JSON应该是

{
  "userId" :2,
  "userName" : "john",
  "emailId" : "john@gmail.com"
}
Run Code Online (Sandbox Code Playgroud)

我不想从其他数据库表发送到客户端的字段列表.所以它会根据登录用户而改变.我该怎么做?

我希望你有我的问题.

use*_*3 ツ 124

@JsonIgnoreProperties("fieldname")注释添加到POJO.

或者,您可以@JsonIgnore在反序列化JSON时在要忽略的字段名称之前使用.例:

@JsonIgnore
@JsonProperty(value = "user_password")
public java.lang.String getUserPassword() {
    return userPassword;
}
Run Code Online (Sandbox Code Playgroud)

GitHub的例子

  • 我可以动态做吗?不在POJO?我可以在我的Controller类中完成吗? (55认同)
  • 评论:`@JsonIgnore`是`com.fasterxml.jackson.annotation.JsonIgnore`不是`org.codehaus.jackson.annotate.JsonIgnore`. (10认同)
  • 在从请求读取和发送响应时忽略这两者.我只想在发送响应时忽略,因为我需要来自请求对象的属性.有任何想法吗? (4认同)
  • @iProgrammer:这里有类似的内容:http://stackoverflow.com/questions/8179986/jackson-change-jsonignore-dynamically (3认同)
  • @iProgrammer:这里非常令人印象深刻的答案http://stackoverflow.com/questions/13764280/how-do-i-exclude-fields-with-jackson-not-using-annotations (3认同)
  • 这不是这个问题的答案。我不明白为什么 @iCode 接受它。 (2认同)

mon*_*jbl 31

我知道我参加聚会有点晚了,但几个月前我也遇到了这个问题.所有可用的解决方案对我来说都不是很吸引人(mixins?唉!),所以我最终创建了一个新的库来使这个过程更加清晰.如果有人想尝试一下,它可以在这里使用:https://github.com/monitorjbl/spring-json-view.

基本用法很简单,你JsonView在控制器方法中使用对象如下:

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"));
}
Run Code Online (Sandbox Code Playgroud)

你也可以在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"));
Run Code Online (Sandbox Code Playgroud)

  • 谢谢!这是我的方式.我需要在不同位置使用相同对象的自定义JSON视图,而@JsonIgnore不起作用.这个库让它变得简单易行. (5认同)
  • 您使我的代码更清晰,实现更容易.谢谢 (2认同)

geo*_*and 11

添加@JsonInclude(JsonInclude.Include.NON_NULL)(强制杰克逊序列化空值)到类和@JsonIgnore密码字段.

你当然可以@JsonIgnore在createdBy和updatedBy上设置,如果你总是想忽略它而不仅仅是在这个特定的情况下.

UPDATE

如果您不想将注释添加到POJO本身,一个很好的选择是Jackson的Mixin Annotations.查看文档


Sha*_*afi 8

是的,您可以指定将哪些字段序列化为JSON响应,而忽略哪些字段。这是实现动态忽略属性所需的操作。

1)首先,您需要在com.fasterxml.jackson.annotation.JsonFilter上的实体类上添加@JsonFilter。

import com.fasterxml.jackson.annotation.JsonFilter;

@JsonFilter("SomeBeanFilter")
public class SomeBean {

  private String field1;

  private String field2;

  private String field3;

  // getters/setters
}
Run Code Online (Sandbox Code Playgroud)

2)然后,在控制器中,您必须添加创建MappingJacksonValue对象并在其上设置过滤器,最后,您必须返回此对象。

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;
  }
}
Run Code Online (Sandbox Code Playgroud)

这是您将得到的响应:

{
  field1:"value1",
  field2:"value2"
}
Run Code Online (Sandbox Code Playgroud)

代替这个:

{
  field1:"value1",
  field2:"value2",
  field3:"value3"
}
Run Code Online (Sandbox Code Playgroud)

在这里,您可以看到它忽略了其他属性(在这种情况下为field3),除了属性field1和field2之外。

希望这可以帮助。


Het*_*ett 7

我可以动态地做吗?

创建视图类:

public class View {
    static class Public { }
    static class ExtendedPublic extends Public { }
    static class Internal extends ExtendedPublic { }
}
Run Code Online (Sandbox Code Playgroud)

注释您的模型

@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
}
Run Code Online (Sandbox Code Playgroud)

在控制器中指定视图类

@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);
    }

}
Run Code Online (Sandbox Code Playgroud)

数据示例:

{"id":"5aa2496df863482dc4da2067","name":"test","createdAt":"2018-03-10T09:35:31.050353800Z"}
Run Code Online (Sandbox Code Playgroud)

  • 这是一个奇妙而简约的答案!我只想以 JSON 形式返回 @Configuration 带注释的组件中的几个字段,并跳过自动包含的所有内部字段。多谢! (3认同)

Ham*_*edz 6

如果我是您并且想要这样做,则不会在Controller层中使用我的User实体,而是创建并使用UserDto(数据传输对象)与业务(Service)层和Controller进行通信。您可以使用Apache BeanUtils(copyProperties方法)将数据从用户实体复制到UserDto。


cee*_*kay 6

我们可以通过JsonProperty.Access.WRITE_ONLY在声明属性时设置对的访问权限来实现。

@JsonProperty( value = "password", access = JsonProperty.Access.WRITE_ONLY)
@SerializedName("password")
private String password;
Run Code Online (Sandbox Code Playgroud)


fox*_*bit 6

我已经解决了只@JsonIgnore像@kryger 建议的那样使用。所以你的 getter 将变成:

@JsonIgnore
public String getEncryptedPwd() {
    return this.encryptedPwd;
}
Run Code Online (Sandbox Code Playgroud)

您可以设置@JsonIgnore等中描述的现场,setter或getter当然这里

而且,如果您只想在序列化端保护加密密码(例如,当您需要登录用户时),请将此@JsonProperty注释添加到您的字段中

@JsonProperty(access = Access.WRITE_ONLY)
private String encryptedPwd;
Run Code Online (Sandbox Code Playgroud)

更多信息在这里


Dev*_*ora 5

我创建了一个 JsonUtil,它可用于在运行时忽略字段,同时给出响应。

用法示例:第一个参数应该是任何 POJO 类(学生),ignoreFields 是您想要在响应中忽略的逗号分隔字段。

 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 "";
   }
 }    
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

179461 次

最近记录:

5 年,11 月 前