如何告诉jackson忽略我无法控制源代码的属性?

mav*_*ick 108 java json jackson

简而言之,我的一个实体有一个GeometryCollection,当你调用"getBoundary"时会抛出一个异常(为什么这是另一本书,现在让我们说这就是它的工作方式).

有没有办法告诉杰克逊不要包括那个特定的吸气剂?我知道当我拥有/控制代码时我可以使用@JacksonIgnore.但事实并非如此,杰克逊通过连续序列化父对象来达到这一点.我在jackson文档中看到了一个过滤选项.这是一个看似合理的解决方案吗?

谢谢!

Ami*_*far 155

你可以使用Jackson Mixins.例如:

class YourClass {
  public int ignoreThis() { return 0; }    
}
Run Code Online (Sandbox Code Playgroud)

有了这个Mixin

abstract class MixIn {
  @JsonIgnore abstract int ignoreThis(); // we don't need it!  
}
Run Code Online (Sandbox Code Playgroud)

有了这个:

objectMapper.getSerializationConfig().addMixInAnnotations(YourClass.class, MixIn.class);
Run Code Online (Sandbox Code Playgroud)

编辑:

感谢评论,使用Jackson 2.5+,API已经改变,应该被调用 objectMapper.addMixIn(Class<?> target, Class<?> mixinSource)

  • 在杰克逊2.2中,它是“ objectMapper.addMixInAnnotations(Class &lt;?&gt; target,Class &lt;?&gt; mixinSource);”。 (3认同)

lal*_*men 64

另一种可能性是,如果要忽略所有未知属性,可以按如下方式配置映射器:

mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Run Code Online (Sandbox Code Playgroud)

  • 如果我们可以将objectMapper配置为仅忽略特定属性,那将是很好的.即报告所有新/未知字段的例外,除了让我们说'myfield'.像`mapper.configure(DeserializationFeature.failOnUnknownPropertiesExcep(new String [] {"myField"}));; (4认同)

Sir*_*dda 24

使用Java类

new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
Run Code Online (Sandbox Code Playgroud)

使用注释

@JsonIgnoreProperties(ignoreUnknown=true)
Run Code Online (Sandbox Code Playgroud)


小智 11

如果您想始终排除任何类的某些属性,您可以使用setMixInResolver方法:

    @JsonIgnoreProperties({"id", "index", "version"})
    abstract class MixIn {
    }

    mapper.setMixInResolver(new ClassIntrospector.MixInResolver(){
        @Override
        public Class<?> findMixInClassFor(Class<?> cls) {
            return MixIn.class;  
        }

        @Override
        public ClassIntrospector.MixInResolver copy() {
            return this;
        }
    });
Run Code Online (Sandbox Code Playgroud)


Fır*_*ÇÜK 10

基于注释的方法更好.但有时需要手动操作.为此,您可以在使用ObjectWriter方法的情况下使用.

ObjectMapper mapper   = new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
ObjectWriter writer   = mapper.writer().withoutAttribute("property1").withoutAttribute("property2");
String       jsonText = writer.writeValueAsString(sourceObject);
Run Code Online (Sandbox Code Playgroud)

  • 这种方法对我不起作用,但 mixin 可以。序列化后我仍然得到被忽略的属性。当我们有 withoutAttribute() 时,为什么我们还要有 mixin ? (11认同)
  • `ObjectWriter.withoutAttribute` 不能按照答案中的建议工作。_attribute_ 不引用输入数据的属性名称,并且永远不会在这样的上下文中引用,如[此评论](https://github.com/FasterXML/jackson-core/issues/700#issuecomment-849182602)中指出的, 例如。此方法似乎适合内部使用,如[此处](https://github.com/FasterXML/jackson-databind/blob/2.13/src/main/java/com/fasterxml/jackson/databind/ Ser/std/StdSerializer.java#L364)。 (3认同)

Sta*_*Man 8

如上所述,混合注释在这里工作得很好.每个属性@JsonIgnore之外的另一种可能性是使用@JsonIgnoreType,如果你有一个永远不应该包含的类型(即如果应该忽略所有GeometryCollection属性的实例).然后,您可以直接添加它(如果您控制类型),或者使用混合,例如:

@JsonIgnoreType abstract class MixIn { }
// and then register mix-in, either via SerializationConfig, or by using SimpleModule
Run Code Online (Sandbox Code Playgroud)

如果你有很多类都有一个'IgnoredType getContext()'访问器,那么这会更方便(许多框架就是这种情况)


mon*_*jbl 5

我有一个类似的问题,但它与Hibernate的双向关系有关.我希望展示关系的一面,并以编程方式忽略另一面,具体取决于我处理的是什么视图.如果你不能这样做,你最终会讨厌StackOverflowException.例如,如果我有这些对象

public class A{
  Long id;
  String name;
  List<B> children;
}

public class B{
  Long id;
  A parent;
}
Run Code Online (Sandbox Code Playgroud)

parent如果我正在查看A,我想以编程方式忽略B中的字段,如果我在看B,则忽略childrenA中的字段.

我开始使用mixins来做到这一点,但很快变得可怕; 你有很多无用的课程,只是为了格式化数据.我最终编写了自己的序列化程序,以更清晰的方式处理它:https://github.com/monitorjbl/json-view.

它允许您以编程方式指定要忽略的字段:

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

List<A> list = getListOfA();
String json = mapper.writeValueAsString(JsonView.with(list)
    .onClass(B.class, match()
        .exclude("parent")));
Run Code Online (Sandbox Code Playgroud)

它还允许您通过通配符匹配器轻松指定非常简化的视图:

String json = mapper.writeValueAsString(JsonView.with(list)
    .onClass(A.class, match()
        .exclude("*")
         .include("id", "name")));
Run Code Online (Sandbox Code Playgroud)

在我原来的情况下,需要像这样的简单视图来显示父/子的最低限度,但它对我们基于角色的安全性也很有用.返回关于对象的较少信息所需的对象的特权较少的视图.

所有这些都来自序列化程序,但我在我的应用程序中使用了Spring MVC.为了使它能够正确处理这些情况,我编写了一个集成,您可以将其放入现有的Spring控制器类中:

@Controller
public class JsonController {
  private JsonResult json = JsonResult.instance();
  @Autowired
  private TestObjectService service;

  @RequestMapping(method = RequestMethod.GET, value = "/bean")
  @ResponseBody
  public List<TestObject> getTestObject() {
    List<TestObject> list = service.list();

    return json.use(JsonView.with(list)
        .onClass(TestObject.class, Match.match()
            .exclude("int1")
            .include("ignoredDirect")))
        .returnValue();
  }
}
Run Code Online (Sandbox Code Playgroud)

两者都可以在Maven Central上找到.我希望它可以帮助其他人,这对杰克逊来说是一个特别难看的问题,对我的案子没有很好的解决方案.