0

For some reason I am not able to hide protected fields (without setter), via ObjectMapper configuration, from being serialized to a JSON string.

My POJO:

public class Item {

    protected String sn;
    private String name;

    public Item(){
        sn = "43254667";
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSn() {
        return sn;
    }

}

My mapper:

mapper.setVisibility(PropertyAccessor.SETTER, Visibility.PUBLIC_ONLY);
mapper.setVisibility(PropertyAccessor.GETTER, Visibility.PUBLIC_ONLY);
mapper.setVisibility(PropertyAccessor.FIELD, Visibility.NONE);

The output is:

{
  "sn" : "43254667",
  "name" : "abc"
}

UPDATE: I cannot modify the Item class, hence I cannot use annotations.

cassiomolin
  • 124,154
  • 35
  • 280
  • 359
yuris
  • 1,109
  • 4
  • 19
  • 33

2 Answers2

2

Use @JsonIgnore

You could annotate the field or method with @JsonIgnore.

It's a marker annotation that indicates that the annotated method or field is to be ignored by introspection-based serialization and deserialization functionality.

Use as following:

public class Item {

    @JsonIgnore
    protected String sn;

    ...
}

Or as following:

public class Item {

    ...

    @JsonIgnore
    public String getSn() {
        return sn;
    }
}

Use @JsonIgnore with mix-ins

Based on your comment, you could use mix-in annotations when modifying the classes is not an option, as described in this answer.

You can think of it as kind of aspect-oriented way of adding more annotations during runtime, to augment statically defined ones.

First, define a mix-in annotation interface (class would do as well):

public interface ItemMixIn {

    @JsonIgnore
    String getSn();
}

Then configure your ObjectMapper to use the defined interface as a mix-in for your POJO:

ObjectMapper mapper = new ObjectMapper();
mapper.addMixIn(Item.class, ItemMixIn.class);

For extra details, check the documentation.

Use a BeanSerializerModifier

Based on your comment, you may consider a BeanSerializerModifier, as following:

public class CustomSerializerModifier extends BeanSerializerModifier {

    @Override
    public List<BeanPropertyWriter> changeProperties(SerializationConfig config,
        BeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) {

        // In this method you can add, remove or replace any of passed properties

        return beanProperties;
    }
}

Then register the custom serializer as a module in your ObjectMapper.

ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new SimpleModule() {

    @Override
    public void setupModule(SetupContext context) {
        super.setupModule(context);
        context.addBeanSerializerModifier(new CustomSerializerModifier());
    }
});
Community
  • 1
  • 1
cassiomolin
  • 124,154
  • 35
  • 280
  • 359
  • 1
    you beat me for fraction of second :p – Amit Apr 25 '17 at 08:18
  • @AmitK I've just seen your comment. Actually 19 seconds! – cassiomolin Apr 25 '17 at 08:19
  • Sorry, forgot to mention that I can't use annotation. – yuris Apr 25 '17 at 08:21
  • 1
    @yuris , thats the first thing which you should mention and why you can't use annotations? – Amit Apr 25 '17 at 08:22
  • AmtiK, yes I forgot to mention that, It's a legacy class. – yuris Apr 25 '17 at 08:25
  • @yuris Then you could use mix-ins. Have a look at this [answer](http://stackoverflow.com/a/38889775/1426227). – cassiomolin Apr 25 '17 at 08:26
  • Well, will wait for other answers if nothing comes will accept yours.. I have a lot of pojo classes like that and creating mix classes for which one is not the best solution.... – yuris Apr 25 '17 at 08:55
  • @yuris The last option is custom serialization. – cassiomolin Apr 25 '17 at 09:00
  • this will require from to create custom class for each pojo as well, right? – yuris Apr 25 '17 at 10:08
  • @yuris You could try a generic one extending [`BeanSerializerModifier`](https://fasterxml.github.io/jackson-databind/javadoc/2.8/com/fasterxml/jackson/databind/ser/BeanSerializerModifier.html). You want to avoid only serialization of protected fields? Is there any other condition? – cassiomolin Apr 25 '17 at 10:24
  • @AmitK _How did you measure the exact number of seconds?_ Hover the comment date/time to see the seconds as well ;) – cassiomolin Apr 25 '17 at 10:26
  • @Cássio Mazzochi Molin, when serializing , those fields with public setters – yuris Apr 27 '17 at 09:44
0

You've instructed your mapper to serialize public getters:

mapper.setVisibility(PropertyAccessor.GETTER, Visibility.PUBLIC_ONLY);

That's why Jackson will serialize the sn field (You have a public getter here in the end).

To get rid of the serialized sn field, simply annotate your getter with @JsonIgnore:

public class Item{
  protected String sn;
  private String name;

  public Item(){
      sn = "43254667";
  }

  public String getName() {
      return name;
  }
  public void setName(String name) {
      this.name = name;
  }
  @JsonIgnore
  public String getSn() {
      return sn;
  }

}

If you cannot annotate your class, you can always write a custom serializer for your POJO or use Mixins

Stefan Haberl
  • 9,812
  • 7
  • 72
  • 81