【问题标题】:How can I get a Jackson mixin to work with private fields?如何让 Jackson mixin 用于私有字段?
【发布时间】:2012-06-11 20:50:20
【问题描述】:

我正在尝试使用 Jackson 2.0 mixins 来序列化一个没有注释的类。

下面的简化源代码。请注意,我没有使用 getter/setter,但我似乎仍然可以使用 mixins according to the documentation

public class NoAnnotation {
   private Date created;
   private String name;

   // make one with some data in it for the test
   static NoAnnotation make() {
      NoAnnotation na= new NoAnnotation();
      na.created = new Date();
      na.name = "FooBear";
      return na;
   }

   // my Mixin "class"
   static class JacksonMixIn {
      JacksonMixIn(@JsonProperty("created") Date created,
                   @JsonProperty("name") String name)
         { /* do nothing */ }
   }

   // test code
   public static void main(String[] args) throws Exception {
      NoAnnotation na = NoAnnotation.make();
      ObjectMapper objectMapper = new ObjectMapper();
      objectMapper.addMixInAnnotations(NoAnnotation.class, JacksonMixIn.class);
      String jsonText = objectMapper.writeValueAsString(na);
      System.out.println(jsonText);
   }
}

当我运行 main 我得到

Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: No serializer found for class com.flyingspaniel.so.NoAnnotation and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationConfig.SerializationFeature.FAIL_ON_EMPTY_BEANS) )
    at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.failForEmpty(UnknownSerializer.java:51)
    at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.serialize(UnknownSerializer.java:25)
    at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:108)
    at com.fasterxml.jackson.databind.ObjectMapper._configAndWriteValue(ObjectMapper.java:2407)
    at com.fasterxml.jackson.databind.ObjectMapper.writeValueAsString(ObjectMapper.java:1983)
    at com.flyingspaniel.so.NoAnnotation.main(NoAnnotation.java:49)

当我按照异常中的说明添加一行时

objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);

我不再收到异常,但结果是一个空的 JSON 对象,{}

如果我公开这些字段,它会起作用,但这不是我想做的事情,因为这不是一个合理的对象设计。

我猜我在某处遗漏了一个基本的“setThis”步骤,但不知道是什么。在这种情况下如何让 mixin 工作?

【问题讨论】:

    标签: java jackson annotations mixins jackson-databind


    【解决方案1】:

    如果你想使用注解混合,正确的声明方式是:

    static class JacksonMixIn {
        @JsonProperty Date created;
        @JsonProperty String name;
    }
    

    以这种方式完成后,您可以控制字段序列化,只需将它们包括/排除在混合中。

    【讨论】:

      【解决方案2】:

      in your self-answer 所述,更改字段可见性检查器将解决这种情况。作为修改ObjectMapper 的替代方法,这可以通过使用@JsonAutoDetect 注释通过纯基于注释的解决方案来完成:

      @JsonAutoDetect(fieldVisibility = Visibility.ANY)
      static class JacksonMixIn {
         JacksonMixIn(@JsonProperty("created") Date created,
                      @JsonProperty("id") int id)
            { /* do nothing */ }
      }
      

      【讨论】:

        【解决方案3】:

        我想通了。如果要访问私有字段,则需要通过添加以下行来使用可见性:

        objectMapper.setVisibilityChecker(VisibilityChecker.Std.defaultInstance()
                .withFieldVisibility(Visibility.ANY));
        

        对于受保护的字段,您也可以使用Visibility.PROTECTED_AND_PUBLIC

        完整示例

        // test code
        public static void main(String[] args) throws Exception {
           NoAnnotation na = NoAnnotation.make();
           ObjectMapper objectMapper = new ObjectMapper();
           objectMapper.addMixInAnnotations(NoAnnotation.class, JacksonMixIn.class);
           objectMapper.setVisibilityChecker(VisibilityChecker.Std.defaultInstance()
                   .withFieldVisibility(Visibility.ANY));
           String jsonText = objectMapper.writeValueAsString(na);
           System.out.println(jsonText);
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-04-25
          • 2019-05-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-10-09
          • 1970-01-01
          相关资源
          最近更新 更多