【问题标题】:Jersey/Jackson @JsonIgnore on setter泽西/杰克逊 @JsonIgnore 在二传手上
【发布时间】:2025-11-24 19:20:05
【问题描述】:

我有一个带有以下注释的类:

class A {
public Map<String,List<String>> references;

@JsonProperty
public Map<String,List<String>> getReferences() {
...
}

@JsonIgnore
public void setReferences(Map<String,List<String>>) {
}
...
}
}

我尝试在反序列化时忽略 json。但它不起作用。总是当 JSON 字符串到达​​ Jackson 库时填充引用属性。如果我只使用 @JsonIgnore 注释,则 getter 不起作用。这个问题有解决办法吗?

谢谢

【问题讨论】:

    标签: java json rest jersey jackson


    【解决方案1】:

    我认为有两个关键部分可以让您根据需要拥有“只读集合”。首先,除了忽略setter,确保你的字段也标有@JsonIgnore:

    class A {
    
      @JsonIgnore
      public Map<String,List<String>> references;
    
      @JsonProperty
      public Map<String,List<String>> getReferences() { ... }
    
      @JsonIgnore
      public void setReferences(Map<String,List<String>>) { ... }
    
    }
    

    其次,为了防止getter被用作setter,禁用USE_GETTERS_AS_SETTERS功能:

    ObjectMapper mapper = new ObjectMapper();
    mapper.disable(MapperFeature.USE_GETTERS_AS_SETTERS);
    

    【讨论】:

    • 我愚蠢地忽略了您的第一个建议并且没有将该字段标记为已忽略,因为在我的情况下它是私有的。但是,我仍然需要这样做,以使其正常工作。这是对的还是我的误解?如果是这样,也许值得在你的回答中明确指出。
    【解决方案2】:

    从 Jackson 2.6 开始,有一种新的改进方法来定义 read-onlywrite-only 属性,使用 JsonProperty#access() 注释。建议不要使用单独的 JsonIgnoreJsonProperty 注释。

    @JsonProperty(access = JsonProperty.Access.READ_ONLY)
    public Map<String,List<String>> references;
    

    【讨论】:

      【解决方案3】:

      您必须确保在字段级别以及 setter 上有 @JsonIgnore 注解,并且在 getter 上使用 @JsonProperty 进行注解。

      public class Echo {
      
          @Null
          @JsonIgnore
          private String doNotDeserialise;
      
          private String echo;
      
          @JsonProperty
          public String getDoNotDeserialise() {
              return doNotDeserialise;
          }
      
          @JsonIgnore
          public void setDoNotDeserialise(String doNotDeserialise) {
              this.doNotDeserialise = doNotDeserialise;
          }
      
          public String getEcho() {
              return echo;
          }
      
          public void setEcho(String echo) {
              this.echo = echo;
          }
      }
      
      @Controller
      public class EchoController {
      
      @ResponseBody
      @RequestMapping(value = "/echo", consumes = APPLICATION_JSON_VALUE, produces = APPLICATION_JSON_VALUE)
          public Echo echo(@RequestBody @Valid Echo echo) {
              if (StringUtils.isEmpty(echo.getDoNotDeserialise())) {
                  echo.setDoNotDeserialise("Value is set by the server, not by the client!");
              }
      
              return echo;
          }
      }
      
      • 如果您提交的 JSON 请求中设置了“doNotDeserialise”值,则当 JSON 反序列化为对象时,它将设置为 null(如果不是,我在字段上设置了验证约束,因此会出错)
      • 如果您将“doNotDeserialise”值设置为服务器上的某个值,那么它将被正确序列化为 JSON 并推送到客户端

      【讨论】:

        【解决方案4】:

        我在我的 getter 上使用了@JsonIgnore,但它不起作用,我无法配置映射器(我使用的是 Jackson Jaxrs 提供程序)。这对我有用:

        @JsonIgnoreProperties(ignoreUnknown = true, value = { "actorsAsString",
            "writersAsString", "directorsAsString", "genresAsString" }) 
        

        【讨论】:

          【解决方案5】:

          我只能想到一个非jackson解决方案,使用一个没有映射引用的基类,然后转换为实际类:

          // expect a B on an incoming request
          class B {
          // ...
          }
          
          // after the data is read, cast to A which will have empty references
          class A extends B {
          public Map<String,List<String>> references;
          }
          

          如果您不想要参考资料,为什么还要发送它们?

          或者是传入的数据不在您的手中,而您只是想避免映射异常告诉您杰克逊找不到要为传入引用设置的属性?为此,我们使用所有 Json 模型类都继承的基类:

          public abstract class JsonObject {
          
              @JsonAnySetter
              public void handleUnknown(String key, Object value) {
          
                  // for us we log an error if we can't map but you can skip that
                  Log log = LogFactory.getLog(String.class);    
                  log.error("Error mapping object of type: " + this.getClass().getName());    
                  log.error("Could not map key: \"" + key + "\" and value: \"" + "\"" + value.toString() + "\"");
          
              }
          

          然后在 POJO 中添加 @JsonIgnoreProperties 以便传入的属性将被转发到 handleUnknown()

          @JsonIgnoreProperties
          class A extends JsonObject {
              // no references if you don't need them
          }
          

          编辑

          This SO Thread 描述了如何使用 Mixins。如果您想保持结构原样,这可能是解决方案,但我还没有尝试过。

          【讨论】:

          • 没错。传入的数据并不真正掌握在我们手中。但是客户端总是以正确的格式发送引用属性,因此永远不会调用 handleUnknown。
          • 啊,我的错,忘记了一点信息。如果您想忽略传入的数据,您需要在 POJO 处使用@JsonIgnoreProperties。我会更新我的帖子。 (PS:我们使用它来消耗 facebook 的 REST 资源,所有从 facebook 发送的不包含在我们的 POJO 中的属性都将被记录下来,然后我们决定是否要添加它们)
          • 但是引用在我的 POJO 中,所以它总是与 setter 匹配
          • 但是如果你不需要它,为什么还要在你的 POJO 中保留引用呢?如果你真的想保持你的确切结构,找到另一个可能适用的解决方案:*.com/questions/7421474/…
          • 感谢您的链接。我以前尝试过 mixins,但它不适合我。挑战在于将引用属性设置为只读状态。这样我就可以向客户端发送信息,但忽略此属性上的传入更改