How can I tell jackson to ignore a property for which I don't have control over the source code?

JavaJsonJackson

Java Problem Overview


Long story short, one of my entities has a GeometryCollection that throws an exception when you call "getBoundary" (the why of this is another book, for now let's say this is the way it works).

Is there a way I can tell Jackson not to include that specific getter? I know I can use @JacksonIgnore when I do own/control the code. But this is not case, jackson ends reaching this point through continuous serialization of the parent objects. I saw a filtering option in jackson documentation. Is that a plausible solution?

Thanks!

Java Solutions


Solution 1 - Java

You can use Jackson Mixins. For example:

class YourClass {
  public int ignoreThis() { return 0; }    
}

With this Mixin

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

With this:

objectMapper.getSerializationConfig().addMixInAnnotations(YourClass.class, MixIn.class);

Edit:

Thanks to the comments, with Jackson 2.5+, the API has changed and should be called with objectMapper.addMixIn(Class<?> target, Class<?> mixinSource)

Solution 2 - Java

One other possibility is, if you want to ignore all unknown properties, you can configure the mapper as follows:

mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

Solution 3 - Java

Using Java Class

new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)

Using Annotation

@JsonIgnoreProperties(ignoreUnknown=true)

Solution 4 - Java

Annotation based approach is better. But sometimes manual operation is needed. For this purpose you can use without method of 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);

Solution 5 - Java

Mix-in annotations work pretty well here as already mentioned. Another possibility beyond per-property @JsonIgnore is to use @JsonIgnoreType if you have a type that should never be included (i.e. if all instances of GeometryCollection properties should be ignored). You can then either add it directly (if you control the type), or using mix-in, like:

@JsonIgnoreType abstract class MixIn { }
// and then register mix-in, either via SerializationConfig, or by using SimpleModule

This can be more convenient if you have lots of classes that all have a single 'IgnoredType getContext()' accessor or so (which is the case for many frameworks)

Solution 6 - Java

I had a similar issue, but it was related to Hibernate's bi-directional relationships. I wanted to show one side of the relationship and programmatically ignore the other, depending on what view I was dealing with. If you can't do that, you end up with nasty StackOverflowExceptions. For instance, if I had these objects

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

public class B{
  Long id;
  A parent;
}

I would want to programmatically ignore the parent field in B if I were looking at A, and ignore the children field in A if I were looking at B.

I started off using mixins to do this, but that very quickly becomes horrible; you have so many useless classes laying around that exist solely to format data. I ended up writing my own serializer to handle this in a cleaner way: https://github.com/monitorjbl/json-view.

It allows you programmatically specify what fields to ignore:

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")));

It also lets you easily specify very simplified views through wildcard matchers:

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

In my original case, the need for simple views like this was to show the bare minimum about the parent/child, but it also became useful for our role-based security. Less privileged views of objects needed to return less information about the object.

All of this comes from the serializer, but I was using Spring MVC in my app. To get it to properly handle these cases, I wrote an integration that you can drop in to existing Spring controller classes:

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

Both are available on Maven Central. I hope it helps someone else out there, this is a particularly ugly problem with Jackson that didn't have a good solution for my case.

Solution 7 - Java

If you want to ALWAYS exclude certain properties for any class, you could use setMixInResolver method:

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

Solution 8 - Java

One more good point here is to use @JsonFilter. Some details here http://wiki.fasterxml.com/JacksonFeatureJsonFilter

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionmaverickView Question on Stackoverflow
Solution 1 - JavaAmir RaminfarView Answer on Stackoverflow
Solution 2 - JavalaloumenView Answer on Stackoverflow
Solution 3 - JavaSireesh YarlagaddaView Answer on Stackoverflow
Solution 4 - JavaFırat KÜÇÜKView Answer on Stackoverflow
Solution 5 - JavaStaxManView Answer on Stackoverflow
Solution 6 - JavamonitorjblView Answer on Stackoverflow
Solution 7 - JavafifmanView Answer on Stackoverflow
Solution 8 - JavaVladimir FilipchenkoView Answer on Stackoverflow